sheet.range(‘U‘ + str(index - 1), ‘U‘ + str(index)).api.merge(),xlwings合并Excel上下相邻单元格,代码中断执行,也不报错。

一、背景

采用xlwings包,根据template.xlsx模板,导出excel成果内容,包括多个sheet内容的填充,可实现上下相邻单元格的合并(左右单元格合并也是一个道理),代码运行卡着,也不报错。

代码需合并U4和U5上下两个单元格;

二、解决方法

修改api.merge()为api.Merge(),虽然鼠标在Merge()方法上面无法跳转,但仍然可用;

sheet.range('U' + str(index - 1), 'U' + str(index)).api.Merge()

完整测试类代码如下:

# -*- coding: utf-8 -*-

"""
@author: tjm
@software: PyCharm
@file: ExcelUtils.py
@time: 2022/4/14 9:54
"""
import os

import xlwings as xw
import pandas as pd
import time


# Excel工具类
class ExcelUtils:
    def __init__(self, template_path=None):
        self.template_path = template_path
        self.app = xw.App(visible=False, add_book=False)
        self.wb = self.app.books.open(self.template_path)

    # 根据模板导出excel文件
    def write2excel(self, excel_name, outcome_data=None, defect_data=None, maintain_data=None, kind_data=None):

        # 1.写入成果表sheet
        self.write_outcome_table(outcome_data)
        # 2.写入管段缺陷表sheet
        self.write_defect_table(defect_data)
        # 3.写入维护管段表sheet
        self.write_maintain_table(maintain_data)
        # 4.写入缺陷种类表sheet
        self.write_kind_table(kind_data)

        self.wb.save('Excels\\' + excel_name)
        self.wb.close()

    # 成果表sheet填充数据
    def write_outcome_table(self, data=None):
        if data is None:
            return
        sheet = self.wb.sheets['成果表']
        # 合并单元格时用
        cur_a, cur_b, cur_c = None, None, None
        for index, row in data.iterrows():
            index += 4
            print("index:", index)
            sheet.range('A' + str(index)).value = row[0]
            sheet.range('B' + str(index)).value = row[1]
            sheet.range('C' + str(index)).value = row[2]

            if index == 4:
                cur_a, cur_b, cur_c = row[0], row[1], row[2]

            sheet.range('D' + str(index)).value = row[3]
            sheet.range('E' + str(index)).value = row[4]
            sheet.range('F' + str(index)).value = row[5]
            sheet.range('G' + str(index)).value = row[6]
            sheet.range('H' + str(index)).value = row[7]
            sheet.range('I' + str(index)).value = row[8]
            sheet.range('J' + str(index)).value = row[9]
            sheet.range('K' + str(index)).value = row[10]
            sheet.range('L' + str(index)).value = row[11]
            sheet.range('M' + str(index)).value = row[12]
            sheet.range('N' + str(index)).value = row[13]
            sheet.range('O' + str(index)).value = row[14]

            # 插入图片
            cell_img = sheet.range('P' + str(index))
            file_name = os.path.join(os.getcwd(), row[15])
            width, height = 140, 80  # 指定图片大小
            left = cell_img.left + (cell_img.width - width) / 2  # 居中
            top = cell_img.top + (cell_img.height - height) / 2
            sheet.pictures.add(file_name, left=left, top=top, width=width, height=height)

            sheet.range('Q' + str(index)).value = row[16]
            sheet.range('R' + str(index)).value = row[17]
            sheet.range('S' + str(index)).value = row[18]
            sheet.range('T' + str(index)).value = row[19]

            if index > 4 and cur_a == row[0] and cur_b == row[1] and cur_c == row[2]:
                sheet.range('U' + str(index - 1), 'U' + str(index)).api.Merge()
            else:
                cur_a, cur_b, cur_c = row[0], row[1], row[2]
                sheet.range('U' + str(index)).value = row[20]

            sheet.range('V' + str(index)).value = row[21]
            sheet.range('W' + str(index)).value = row[22]
            sheet.range('X' + str(index)).value = row[23]
            sheet.range('Y' + str(index)).value = row[24]
            if row[24] == 'Ⅳ':
                sheet.range('Y' + str(index)).color = (225, 0, 0)
            elif row[24] == 'Ⅲ':
                sheet.range('Y' + str(index)).color = (225, 165, 0)
            elif row[24] == 'Ⅱ':
                sheet.range('Y' + str(index)).color = (225, 255, 0)
            sheet.range('Z' + str(index)).value = row[25]
            sheet.range('AA' + str(index)).value = row[26]
            sheet.range('AB' + str(index)).value = row[27]
            sheet.range('AC' + str(index)).value = row[28]
            sheet.range('AD' + str(index)).value = row[29]
            sheet.range('AE' + str(index)).value = row[30]
            if row[30] == 'Ⅳ':
                sheet.range('AE' + str(index)).color = (225, 0, 0)
            elif row[30] == 'Ⅲ':
                sheet.range('AE' + str(index)).color = (225, 165, 0)
            elif row[30] == 'Ⅱ':
                sheet.range('AE' + str(index)).color = (225, 255, 0)
            sheet.range('AF' + str(index)).value = row[31]

    # 管段缺陷表sheet填充数据
    def write_defect_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['管段缺陷表']
        for index, row in data.iterrows():
            index += 4
            sheet.range('D' + str(index)).value = row[0]
            sheet.range('E' + str(index)).value = row[1]

    # 维护管段表sheet填充数据
    def write_maintain_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['维护管段表']
        for index, row in data.iterrows():
            index += 4
            sheet.range('C' + str(index)).value = row[0]
            sheet.range('D' + str(index)).value = row[1]
            sheet.range('E' + str(index)).value = row[2]
            sheet.range('F' + str(index)).value = row[3]

    # 缺陷种类表sheet填充数据
    def write_kind_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['缺陷种类表']
        for index, row in data.iterrows():
            index += 3
            sheet.range('C' + str(index)).value = row[0]
            sheet.range('D' + str(index)).value = row[1]
            sheet.range('E' + str(index)).value = row[2]
            sheet.range('F' + str(index)).value = row[3]
            sheet.range('G' + str(index)).value = row[4]


# 测试入口方法
if __name__ == "__main__":
    excel = ExcelUtils(template_path='Excels\\cctv_template.xlsx')
    tep_time = time.strftime("%Y%m%d%H%M%S")
    print(tep_time)
    exl_name = '陈村大道排水管道内窥检测与评估成果表_' + tep_time + '.xlsx'

    outcome_dat = pd.DataFrame(data=[['陈村大道', 'N0630YS1096', 'N0630WS1097', 'WS', '混凝土管', '300', '8.7', '8.7', '1.6',
                                      '1.54', '2.50m-2.50m,1212h', '结构性缺陷', '破裂', 'PL', '4', r'Excels\imgs\froge.jpg',
                                      '管道材料破碎处边缘环向覆盖范围>弧长60度。', 'QV',
                                      '逆流', '2022/03/12', '11', '10', '0.23', '8.3', 'Ⅳ',
                                      '管道过流受阻很严重,即将或已经导致运行瘫痪;输水功能受到严重影响,应立即进行处理',
                                      '4', '10', '0.06', '9.05', 'Ⅳ', '管道过流受阻很严重,即将或已经导致运行瘫痪。'
                                      ],
                                     ['陈村大道', 'N0630YS1096', 'N0630WS1097', 'WS', '混凝土管', '300', '8.7', '8.7', '1.6',
                                      '1.54', '2.00m-2.00m,1212h', '结构性缺陷', '错口', 'CK', '2', r'Excels\imgs\grass.jpg',
                                      '相接的两个管口偏差为管壁厚度的1/2-1之间。', 'QV',
                                      '逆流', '2022/03/12', '11', '10', '0.23', '8.3', 'Ⅳ',
                                      '管道过流受阻很严重,即将或已经导致运行瘫痪;输水功能受到严重影响,应立即进行处理',
                                      '4', '10', '0.06', '9.05', 'Ⅳ', '管道过流受阻很严重,即将或已经导致运行瘫痪。'
                                      ]
                                     ],
                               columns=['工程名称', '起始井号', '终止井号', '管段类型', '管段材质', '管段直径', '管段长度', '检测长度', '起点埋深',
                                        '终点埋深', '缺陷位置', '缺陷类型', '缺陷名称', '缺陷代码', '缺陷等级', '检测图片', '检测描述', '检测方法',
                                        '检测方向', '检测日期', '平均值S', 'JG最大值Smax', 'JG缺陷密度', '修复指数', '修复等级', '修复建议',
                                        '平均值Y', 'GN最大值Smax', 'GN缺陷密度', '养护指数', '养护等级', '养护建议'])

    defect_dat = pd.DataFrame(data=[['N0630YS1099~N0630YS1096', '1'], [
        'N0630YS1096~N0630YS1095、N0630YS1099~N0630YS1096', '2'], [
                                        'N0630YS1096~N0630YS1095', '1']],
                              columns=['缺陷管段', '管段数量'])

    maintain_dat = pd.DataFrame(data=[['N0630YS1099~N0630YS1096', '1', '0.2', '结构基本完好,不修复'], [
        'N0630YS1096~N0630YS1095、N0630YS1099~N0630YS1096、N0630WS1097~N0630YS1096、N0630YS1095~N0630YS1094', '4', '0.8',
        '结构在短期内不会发生破坏,但应做修复计划'], [
                                          'N0630YS1096~N0630YS1095', '1', '0.2', '结构在短期内可能会发生破坏,应尽快修复'],
                                      ['N0630WS1097~N0630YS1096、N0630YS1095~N0630YS1094', '2', '0.4',
                                       '结构已经发生或即将发生破坏,应立即修复']],
                                columns=['维护管段', '管段数量(段)', '管段占比(%)', '维护建议'])

    kind_dat = pd.DataFrame(data=[['1', '3', '1', '2', '7'], ['-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-'],
                                  ['-', '-', '-', '-', '-']],
                            columns=['1级', '2级', '3级', '4级', '合计'])

    excel.write2excel(excel_name=exl_name, outcome_data=outcome_dat, defect_data=defect_dat, maintain_data=maintain_dat,
                      kind_data=kind_dat)

 代码可正常运行,合并单元格成功。

 虚拟环境如下:

(py36_excel_env) C:\Users\DELL>pip list
Package           Version
----------------- -------------------
absl-py           0.13.0
astunparse        1.6.3
certifi           2020.6.20
flatbuffers       1.12
google-pasta      0.2.0
keras-nightly     2.5.0.dev2021032900
numpy             1.19.5
object-detection  0.1
pandas            1.1.5
pip               21.2.2
python-dateutil   2.8.2
pytz              2021.3
pywin32           302
setuptools        58.0.4
six               1.16.0
typing-extensions 3.7.4.3
wheel             0.37.0
wincertstore      0.2
xlwings           0.25.2

三、备注:

合并多个上下单元格:

代码如下:

# -*- coding: utf-8 -*-

"""
@author: tjm
@software: PyCharm
@file: ExcelUtils.py
@time: 2022/4/14 9:54
"""
import os

import xlwings as xw
import pandas as pd
import time


# Excel工具类
class ExcelUtils:
    def __init__(self, template_path=None):
        self.template_path = template_path
        self.app = xw.App(visible=False, add_book=False)
        self.wb = self.app.books.open(self.template_path)

    # 根据模板导出excel文件
    def write2excel(self, excel_name, outcome_data=None, defect_data=None, maintain_data=None, kind_data=None):

        # 1.写入成果表sheet
        self.write_outcome_table(outcome_data)
        # 2.写入管段缺陷表sheet
        self.write_defect_table(defect_data)
        # 3.写入维护管段表sheet
        self.write_maintain_table(maintain_data)
        # 4.写入缺陷种类表sheet
        self.write_kind_table(kind_data)

        self.wb.save('Excels\\' + excel_name)
        self.wb.close()

    # 成果表sheet填充数据
    def write_outcome_table(self, data=None):
        if data is None:
            return
        sheet = self.wb.sheets['成果表']
        # 合并单元格时用
        cur_a, cur_b, cur_c = None, None, None
        for index, row in data.iterrows():
            index += 4
            print("index:", index)
            sheet.range('A' + str(index)).value = row[0]
            sheet.range('B' + str(index)).value = row[1]
            sheet.range('C' + str(index)).value = row[2]

            if index == 4:
                cur_a, cur_b, cur_c = row[0], row[1], row[2]

            sheet.range('D' + str(index)).value = row[3]
            sheet.range('E' + str(index)).value = row[4]
            sheet.range('F' + str(index)).value = row[5]
            sheet.range('G' + str(index)).value = row[6]
            sheet.range('H' + str(index)).value = row[7]
            sheet.range('I' + str(index)).value = row[8]
            sheet.range('J' + str(index)).value = row[9]
            sheet.range('K' + str(index)).value = row[10]
            sheet.range('L' + str(index)).value = row[11]
            sheet.range('M' + str(index)).value = row[12]
            sheet.range('N' + str(index)).value = row[13]
            sheet.range('O' + str(index)).value = row[14]

            # 插入图片
            cell_img = sheet.range('P' + str(index))
            file_name = os.path.join(os.getcwd(), row[15])
            width, height = 140, 80  # 指定图片大小
            left = cell_img.left + (cell_img.width - width) / 2  # 居中
            top = cell_img.top + (cell_img.height - height) / 2
            sheet.pictures.add(file_name, left=left, top=top, width=width, height=height)

            sheet.range('Q' + str(index)).value = row[16]
            sheet.range('R' + str(index)).value = row[17]
            sheet.range('S' + str(index)).value = row[18]
            sheet.range('T' + str(index)).value = row[19]

            # 合并上下单元格(结构性和功能性缺陷指标)
            if index > 4 and cur_a == row[0] and cur_b == row[1] and cur_c == row[2]:
                sheet.range('U' + str(index - 1), 'U' + str(index)).api.Merge()
                sheet.range('V' + str(index - 1), 'V' + str(index)).api.Merge()
                sheet.range('W' + str(index - 1), 'W' + str(index)).api.Merge()
                sheet.range('X' + str(index - 1), 'X' + str(index)).api.Merge()
                sheet.range('Y' + str(index - 1), 'Y' + str(index)).api.Merge()
                sheet.range('Z' + str(index - 1), 'Z' + str(index)).api.Merge()
                sheet.range('AA' + str(index - 1), 'AA' + str(index)).api.Merge()
                sheet.range('AB' + str(index - 1), 'AB' + str(index)).api.Merge()
                sheet.range('AC' + str(index - 1), 'AC' + str(index)).api.Merge()
                sheet.range('AD' + str(index - 1), 'AD' + str(index)).api.Merge()
                sheet.range('AE' + str(index - 1), 'AE' + str(index)).api.Merge()
                sheet.range('AF' + str(index - 1), 'AF' + str(index)).api.Merge()
            else:
                cur_a, cur_b, cur_c = row[0], row[1], row[2]
                sheet.range('U' + str(index)).value = row[20]
                sheet.range('V' + str(index)).value = row[21]
                sheet.range('W' + str(index)).value = row[22]
                sheet.range('X' + str(index)).value = row[23]
                sheet.range('Y' + str(index)).value = row[24]
                sheet.range('Z' + str(index)).value = row[25]
                sheet.range('AA' + str(index)).value = row[26]
                sheet.range('AB' + str(index)).value = row[27]
                sheet.range('AC' + str(index)).value = row[28]
                sheet.range('AD' + str(index)).value = row[29]
                sheet.range('AE' + str(index)).value = row[30]
                sheet.range('AF' + str(index)).value = row[31]

            # 根据修复等级,设置背景色
            if row[24] == 'Ⅳ':
                sheet.range('Y' + str(index)).color = (225, 0, 0)
            elif row[24] == 'Ⅲ':
                sheet.range('Y' + str(index)).color = (225, 165, 0)
            elif row[24] == 'Ⅱ':
                sheet.range('Y' + str(index)).color = (225, 255, 0)

            if row[30] == 'Ⅳ':
                sheet.range('AE' + str(index)).color = (225, 0, 0)
            elif row[30] == 'Ⅲ':
                sheet.range('AE' + str(index)).color = (225, 165, 0)
            elif row[30] == 'Ⅱ':
                sheet.range('AE' + str(index)).color = (225, 255, 0)

    # 管段缺陷表sheet填充数据
    def write_defect_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['管段缺陷表']
        for index, row in data.iterrows():
            index += 4
            sheet.range('D' + str(index)).value = row[0]
            sheet.range('E' + str(index)).value = row[1]

    # 维护管段表sheet填充数据
    def write_maintain_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['维护管段表']
        for index, row in data.iterrows():
            index += 4
            sheet.range('C' + str(index)).value = row[0]
            sheet.range('D' + str(index)).value = row[1]
            sheet.range('E' + str(index)).value = row[2]
            sheet.range('F' + str(index)).value = row[3]

    # 缺陷种类表sheet填充数据
    def write_kind_table(self, data):
        if data is None:
            return
        sheet = self.wb.sheets['缺陷种类表']
        for index, row in data.iterrows():
            index += 3
            sheet.range('C' + str(index)).value = row[0]
            sheet.range('D' + str(index)).value = row[1]
            sheet.range('E' + str(index)).value = row[2]
            sheet.range('F' + str(index)).value = row[3]
            sheet.range('G' + str(index)).value = row[4]


# 测试入口方法
if __name__ == "__main__":
    excel = ExcelUtils(template_path='Excels\\cctv_template.xlsx')
    tep_time = time.strftime("%Y%m%d%H%M%S")
    print(tep_time)
    exl_name = '陈村大道排水管道内窥检测与评估成果表_' + tep_time + '.xlsx'

    outcome_dat = pd.DataFrame(data=[['陈村大道', 'N0630YS1096', 'N0630WS1097', 'WS', '混凝土管', '300', '8.7', '8.7', '1.6',
                                      '1.54', '2.50m-2.50m,1212h', '结构性缺陷', '破裂', 'PL', '4', r'Excels\imgs\froge.jpg',
                                      '管道材料破碎处边缘环向覆盖范围>弧长60度。', 'QV',
                                      '逆流', '2022/03/12', '11', '10', '0.23', '8.3', 'Ⅳ',
                                      '管道过流受阻很严重,即将或已经导致运行瘫痪;输水功能受到严重影响,应立即进行处理',
                                      '4', '10', '0.06', '9.05', 'Ⅳ', '管道过流受阻很严重,即将或已经导致运行瘫痪。'
                                      ],
                                     ['陈村大道', 'N0630YS1096', 'N0630WS1097', 'WS', '混凝土管', '300', '8.7', '8.7', '1.6',
                                      '1.54', '2.00m-2.00m,1212h', '结构性缺陷', '错口', 'CK', '2', r'Excels\imgs\grass.jpg',
                                      '相接的两个管口偏差为管壁厚度的1/2-1之间。', 'QV',
                                      '逆流', '2022/03/12', '11', '10', '0.23', '8.3', 'Ⅳ',
                                      '管道过流受阻很严重,即将或已经导致运行瘫痪;输水功能受到严重影响,应立即进行处理',
                                      '4', '10', '0.06', '9.05', 'Ⅳ', '管道过流受阻很严重,即将或已经导致运行瘫痪。'
                                      ]
                                     ],
                               columns=['工程名称', '起始井号', '终止井号', '管段类型', '管段材质', '管段直径', '管段长度', '检测长度', '起点埋深',
                                        '终点埋深', '缺陷位置', '缺陷类型', '缺陷名称', '缺陷代码', '缺陷等级', '检测图片', '检测描述', '检测方法',
                                        '检测方向', '检测日期', '平均值S', 'JG最大值Smax', 'JG缺陷密度', '修复指数', '修复等级', '修复建议',
                                        '平均值Y', 'GN最大值Smax', 'GN缺陷密度', '养护指数', '养护等级', '养护建议'])

    defect_dat = pd.DataFrame(data=[['N0630YS1099~N0630YS1096', '1'], [
        'N0630YS1096~N0630YS1095、N0630YS1099~N0630YS1096', '2'], [
                                        'N0630YS1096~N0630YS1095', '1']],
                              columns=['缺陷管段', '管段数量'])

    maintain_dat = pd.DataFrame(data=[['N0630YS1099~N0630YS1096', '1', '0.2', '结构基本完好,不修复'], [
        'N0630YS1096~N0630YS1095、N0630YS1099~N0630YS1096、N0630WS1097~N0630YS1096、N0630YS1095~N0630YS1094', '4', '0.8',
        '结构在短期内不会发生破坏,但应做修复计划'], [
                                          'N0630YS1096~N0630YS1095', '1', '0.2', '结构在短期内可能会发生破坏,应尽快修复'],
                                      ['N0630WS1097~N0630YS1096、N0630YS1095~N0630YS1094', '2', '0.4',
                                       '结构已经发生或即将发生破坏,应立即修复']],
                                columns=['维护管段', '管段数量(段)', '管段占比(%)', '维护建议'])

    kind_dat = pd.DataFrame(data=[['1', '3', '1', '2', '7'], ['-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-'],
                                  ['-', '-', '-', '-', '-']],
                            columns=['1级', '2级', '3级', '4级', '合计'])

    excel.write2excel(excel_name=exl_name, outcome_data=outcome_dat, defect_data=defect_dat, maintain_data=maintain_dat,
                      kind_data=kind_dat)

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,让我解释一下你的问题,你想使用 xlwingsExcel 中实现一个功能。你需要使用 for 循环来遍历从 H 列第 15 行开始的每一行,然后做以下步骤: 1. 逐行确认,如果第一个单元格有值,则将该单元格的值作为 current_cell,否则跳过到下一行进行确认。 2. 直到某行有值的单元格与前一次有值的一行的单元格的值不相等,即 current_cell.value 不等于 prev_cell.value 时,将该行作为下一次比较的起始行 Start_row。 3. 将 current_cell 所在行的上一行与 Start_row 进行单元格合并。 4. 重复步骤 1-3 直到遍历到最后一行。 5. 将 current_cell 的值作为该合并单元格的最终值。 你需要编写代码来实现这个功能。以下是一个示例代码,你可以根据需要进行修改和调整: ```python import xlwings as xw # 打开 Excel 文件 wb = xw.Book('example.xlsx') sheet = wb.sheets['Sheet1'] # 定义起始行和起始单元格 start_row = 15 current_cell = sheet.range('H' + str(start_row)) # 循环遍历每一行 while current_cell.value is not None: prev_cell = current_cell current_row = current_cell.row # 查找下一行第一个非空单元格 while sheet.range('H' + str(current_row + 1)).value is None: current_row += 1 # 如果已经到达最后一行,则退出循环 if current_row >= sheet.api.Rows.Count: break # 如果已经到达最后一行,则退出循环 if current_row >= sheet.api.Rows.Count: break current_cell = sheet.range('H' + str(current_row + 1)) # 如果当前单元格与前一个单元格的值不相等,则合并单元格 if current_cell.value != prev_cell.value: merge_range = sheet.range('H' + str(start_row - 1) + ':H' + str(current_row - 1)) merge_range.merge() start_row = current_row # 将最后一次合并单元格合并 merge_range = sheet.range('H' + str(start_row - 1) + ':H' + str(current_row)) merge_range.merge() # 将 current_cell 的值作为该合并单元格的最终值 merge_range.value = current_cell.value # 关闭 Excel 文件 wb.save() wb.close() ``` 希望这可以帮到你。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值