首页 > 解决方案 > 自定义 Ansible 模块 Python XlSXWRITER 无法格式化大于 Z 的行

问题描述

这个 Ansible 模块以 xlsx 格式转换和组合 csv 文件。

我已经复制了模块https://github.com/giovannisciortino/ansible-generate-report并进行了一些格式更改,例如对齐方式,并且其他模块对于小于宽度小于 Z 的工作表的行工作正常,它会在大于 Z 的列上引发错误,例如 AA AB 。

我们能否添加将 csv 转换为宽度更大的 xlsx 的功能。

我的代码如下:

#!/usr/bin/python

from ansible.module_utils.basic import *
import sys
import os
import csv
import xlsxwriter
import glob


def main():
    fields = {
        "csv_dir": {"required": True, "type": "str"},
        "output_xlsx_file": {"required": True, "type": "str"},
        "format_header": {"required": True, "type": "bool"},
        # if defined use this csv list as first sheets of the workbook
        "summary_csv_list": {"required": False, "type": "list", "default": []},
    }

    module = AnsibleModule(argument_spec=fields)

    wb = xlsxwriter.Workbook(module.params['output_xlsx_file'])
    format_header = wb.add_format({'border': 1})
    format_header.set_bold()
    format_header.set_bg_color('red')
    format_header.set_font_color('white')
    format_header.set_text_wrap()
    format_header.set_align('center')
    format_header.set_align('vcenter')

    cell_format = wb.add_format({'border': 1})
    cell_format.set_center_across('center_across')
    cell_format.set_align('left')
    cell_format.set_align('vcenter')

    csv_dir = module.params['csv_dir']
    csv_file_list = sorted(glob.glob(csv_dir + '/*.csv'))

    for summary_filename_csv in reversed(module.params['summary_csv_list']):
        summary_filename = csv_file_list.index(csv_dir + '/' + summary_filename_csv)
        csv_file_list.insert(0, csv_file_list.pop(summary_filename))

    for csv_file_path in csv_file_list:

        sheet_title = os.path.splitext(os.path.basename(csv_file_path))[0][0:31]
        ws = wb.add_worksheet(sheet_title)

        with open(csv_file_path, 'r') as csvfile:
            table = csv.reader(csvfile)
            num_row = 0
            num_cols = 0
            columns_width = []
            for row in table:
                if module.params['format_header'] and num_row == 0:
                    ws.write_row(num_row, 0, row, format_header)
                else:
                    ws.write_row(num_row, 0, row, cell_format)

                num_row += 1
                num_cols = max(num_cols, len(row))
                columns_width = [max(len(j), columns_width[i] if len(columns_width) > i else 1) for i, j in enumerate(row)]
            # Simulate autofit column
            for i, j in enumerate(columns_width):
                column_name = "%s:%s" % (chr(ord('A') + i), chr(ord('A') + i))
                ws.set_column(column_name, j)

        if module.params['format_header']:
            ws.autofilter(0, 0, num_row-1, num_cols-1)

    wb.close()

    response = {"result": "file %s created" % (module.params['output_xlsx_file'])}
    module.exit_json(changed=False, meta=response)


if __name__ == '__main__':
    main()

宽度较大的纸张上的 Ansible 错误,如 columa AA AB

任务 [生成报告] ************************************************ *********** 任务执行过程中出现异常。要查看完整的回溯,请使用 -vvv。错误是:AttributeError:“NoneType”对象没有属性“组”致命:[localhost]:失败!=> {"changed": false, "module_stderr": "Traceback (last last last call):\n File "/root/.ansible/tmp/ansible-tmp-1603338799.11-110921-229302004092192/AnsiballZ_xlswriter.py", line 102,在 \n _ansiballz_main()\n 文件“/root/.ansible/tmp/ansible-tmp-1603338799.11-110921-229302004092192/AnsiballZ_xlswriter.py”中,第 94 行,在 _ansiballz_main\n 调用模块(zipped_mod,temp_path,ANSIBALLZ_PARAMS) \n 文件“/root/.ansible/tmp/ansible-tmp-1603338799.11-110921-229302004092192/AnsiballZ_xlswriter.py”,第 40 行,主要的', alter_sys=True)\n 文件 "/usr/lib64/python2.7/runpy.py", 第 176 行, 在 run_module\n fname, loader, pkg_name)\n 文件 "/usr/lib64/python2.7/ runpy.py",第 82 行,在 _run_module_code\n mod_name、mod_fname、mod_loader、pkg_name)\n 文件 "/usr/lib64/python2.7/runpy.py",第 72 行,在 _run_code\n 执行代码在 run_globals\ n 文件“/tmp/ansible_xlswriter_payload_TOQ4f5/ansible_xlswriter_payload.zip/ansible/modules/xlswriter.py”,第 77 行,\n 文件“/tmp/ansible_xlswriter_payload_TOQ4f5/ansible_xlswriter_payload.zip/ansible/modules/xlswriter.py”,第 65 行,在 main\n 文件“/usr/lib/python2.7/site-packages/xlsxwriter/worksheet.py”中,第 120 行,在 column_wrapper\n _, col_1 = xl_cell_to_rowcol(cell_1)\n 文件“/usr/lib/ python2.7/site-packages/xlsxwriter/utility.py”,第 121 行,在 xl_cell_to_rowcol\n col_str = match.group(2)\nAttributeError: 'NoneType' object has no attribute 'group'\n", "module_stdout": "", "msg": "MODULE FAILURE\n有关确切的错误”,“rc”:1} ...忽略


标签: pythonansibleexport-to-excelxlsxwriter

解决方案


这部分代码的逻辑只适用于'A'到'Z':


for i, j in enumerate(columns_width):
    column_name = "%s:%s" % (chr(ord('A') + i), chr(ord('A') + i))
    ws.set_column(column_name, j)

而不是试图计算出像使用符号而不是符号更简单的范围(请AA:AA参阅Cell Notation 上的 XlsxWriter 文档):set_column()(row, col)A1


for i, j in enumerate(columns_width):
    ws.set_column(i, i, j)

推荐阅读