从一张excel中将数据复制到另一张excel中对应列出错了

来源:2-2 文件的复制

星辰奕奕

2025-04-03 21:00:51

import xlwings as xw
from typing import Dict
from openpyxl import load_workbook


def get_merged_column_names(target_path: str, target_sheet: str, header_row: int = 4) -> list:
    wb = load_workbook(target_path, read_only=False)
    ws = wb[target_sheet]
    headers = []
    seen_headers = set()

    for idx, cell in enumerate(ws[header_row]):
        header_value = ""
        merged = False

        # 检查合并区域
        for merged_range in ws.merged_cells.ranges:
            if cell.coordinate in merged_range:
                start_cell = merged_range.start_cell
                header_value = str(start_cell.value).strip() if start_cell.value else ""
                merged = True
                break

        # 非合并单元格处理
        if not merged:
            header_value = str(cell.value).strip() if cell.value else ""

        # 跳过空列名
        if not header_value:
            headers.append(None)
            continue

        # 处理重复列名
        if header_value in seen_headers:
            header_value = f"{header_value}_{idx}"
        seen_headers.add(header_value)
        headers.append(header_value)

    wb.close()
    return headers


def copy_columns_by_name(
    source_path: str,
    source_sheet: str,
    target_path: str,
    target_sheet: str,
    column_map: Dict[str, str],  # 格式: {"源列名": "目标列名"}
):
    """
    将源表指定列数据复制到目标表同名列,保持目标列格式不变
    """
    # 启动 WPS 进程
    app = xw.App(visible=False)  # 若需要调试可改为 visible=True

    source_wb = None  # 初始化变量
    target_wb = None  # 初始化变量

    try:
        # 打开源文件和目标文件
        source_wb = app.books.open(source_path)
        target_wb = app.books.open(target_path)

        # 定位工作表
        source_ws = source_wb.sheets[source_sheet]
        target_ws = target_wb.sheets[target_sheet]

        # # 获取目标表的列名与索引映射
        # target_headers = target_ws.range("A4").expand("right").value
        # target_col_indices = {
        #     str(header).strip(): idx + 1  # 索引从1开始
        #     for idx, header in enumerate(target_headers)
        # }

        # 获取目标表的列名(通过 openpyxl 处理合并单元格)
        target_headers = get_merged_column_names(target_path, target_sheet, header_row=4)
        target_col_indices = {
            header: idx + 1
            for idx, header in enumerate(target_headers)
            if header and str(header).strip() != "None"  # 过滤空值或"None"
        }
        # 在获取 target_col_indices 后添加
        print("目标列名与索引:", target_col_indices)

        # 验证目标列是否存在
        missing_columns = [
            target_col
            for target_col in column_map.values()
            if target_col not in target_col_indices
        ]
        if missing_columns:
            raise ValueError(f"目标表中缺失以下列: {missing_columns}")

        # 遍历源表数据并复制
        source_headers = source_ws.range("A1").expand("right").value
        max_row = source_ws.range("A1").expand("down").last_cell.row

        for src_col_name, tgt_col_name in column_map.items():
            # 获取源列索引
            src_col_idx = source_headers.index(src_col_name) + 1

            # 获取目标列索引
            tgt_col_idx = target_col_indices[tgt_col_name]
            # print(f"目标列名: {tgt_col_name}, 目标列索引: {tgt_col_idx}")  # 调试
            print(f"正在复制列:'{src_col_name}'(索引 {src_col_idx}) → 目标列 '{tgt_col_name}'(索引 {tgt_col_idx})")

            # 批量复制数据(保留目标格式)
            source_data = source_ws.range(
                (2, src_col_idx), (max_row, src_col_idx)
            ).value
            target_ws.range(
                (5, tgt_col_idx), (max_row, tgt_col_idx)
            ).value = source_data

        target_wb.save()
        print("数据复制完成,目标格式已保留!")

    except Exception as e:
        print(f"错误: {str(e)}")
    finally:
        if source_wb:
            source_wb.close()
        if target_wb:
            target_wb.close()
        app.quit()


# 示例调用(直接使用列名映射)
if __name__ == "__main__":
    column_maping = {
        "采样时间": "Date and time",  # 示例:映射到目标文件不存在的列时自动创建
        "comp": "Comp shell", "suction": "Suction", "discharge": "discharge", "filter": "filter",
        "con_in": "Cond In", "con_middle": "Cond middle", "con_out": "Cond Out",
        "eva_in": "Eva In", "eva_out": "Eva Out",

        # "6-1": "6-1", "6-2": "6-2", "6-3": "6-3", "6-4": "6-4",
        # "5-1": "5-1", "5-2": "5-2", "5-3": "5-3", "5-4": "5-4",
        # "4-1": "4-1", "4-2": "4-2", "4-3": "4-3", "4-4": "4-4",
        "3-1": "3-1", "3-2": "3-2", "3-3": "3-3", "3-4": "3-4",  # 示例:多源列映射到同一目标列
        "2-1": "2-1", "2-2": "2-2", "2-3": "2-3", "2-4": "2-4",
        "1-1": "1-1", "1-2": "1-2", "1-3": "1-3", "1-4": "1-4",

        "V": "V", "A": "A", "W": "W", "KWh": "kWh", "PF": "PF", "Hz": "VHz",
        "DB": "DB(℃)", "RH_Adjusted": "RH(%)"
    }

    copy_columns_by_name(
        source_path=r"C:\Users\37747\Desktop\Cleaned_BR375K1能耗Active241017.xlsx",
        source_sheet="Sheet1",
        target_path=r"C:\Users\37747\Desktop\SKG BR375 K4 Energy comsuption test report.xlsx",
        target_sheet="DATA(Active)",
        column_map=column_maping
    )

问题描述:

为什么运行这段代码,没有被正确写入到目标列,而是写入到了A5所在行?索引号对应好像没问题啊,复制写入那段好像也没问题啊!怎么回事?

相关截图:

https://img1.sycdn.imooc.com/climg/56f5406709ee860113990825.jpghttps://img1.sycdn.imooc.com/climg/d43c776709ee862f13620798.jpg

写回答

1回答

好帮手慕小猿

2025-04-07

同学,你好!非课程中的作业或者练习,不在服务之内。同学可以找找其它平台或者资源解决下问题。

祝学习愉快~


0

Python全能工程师

8阶段5大热门领域,从入门到实战,带你从零基础晋级全能,全面提升就业力

1606 学习 · 989 问题

查看课程