【小工具-生成合并文件】使用python实现2个excel文件根据主键合并生成csv文件

news2024/11/20 18:22:39

1 小工具说明

1.1 功能说明

一般来说,我们会先有一个老的文件,这个文件内容是定制好相关列的表格,作为每天的报告。
当下一天来的时候,需要根据新的报表文件和昨天的报表文件做一个合并,合并的时候就会出现有些事新增条目、有些是可能要删除的条目、有些是要更新状态的条目。
当前使用python编写的练习就是达到这个简单目的。

1.2 配置文件

配置文件内容样例:

yesterday=F:\projects\daily_merge_tool\test_files\scene1_no_diff\yesterday.xlsx
today=F:\projects\daily_merge_tool\test_files\scene1_no_diff\today.xlsx
report=F:\projects\daily_merge_tool\test_files\scene1_no_diff\report.csv
yesterday_primary_key_column=D
yesterday_status_column=E
today_primary_key_column=F
today_status_column=E
today_mapping_yesterday=C:B,D:C,F:D,E:E,H:F,I:G,J:H,K:I,L:J,M:K

yesterday的值为昨天的报表文件绝对路径
today的值为今天从其他系统新导出来的报表文件的绝对路径
report的值为存放合并当天最新报表的csv文件的绝对路径
yesterday_primary_key_column的值为昨天的报表文件中能够唯一代表一行数据的属性所在的列,例如:如果值是字母A是excel表格的第一列
yesterday_status_column的值为昨天的报表文件中当前行数据的状态列,例如:如果值是字母A是excel表格的第一列
today_primary_key_column值为今天的报表文件中能够唯一代表一行数据的属性所在的列,例如:如果值是字母A是excel表格的第一列
today_status_column的值为今天的报表文件中当前行数据的状态列,例如:如果值是字母A是excel表格的第一列
today_mapping_yesterday的值为昨天报表文件中各个列的数据来源映射到今天新导出的报表文件中的列

1.3 几个文件的样例

yesterday.xlsx
在这里插入图片描述
today.xlsx
在这里插入图片描述
生成的report.csv,相比yesterday.xlsx,增加了1列Tag,标示当前行是新加还是修改了状态还是确认是否要删除
在这里插入图片描述

2 工具代码

https://download.csdn.net/download/WolfOfSiberian/88399882

import sys
import datetime
import xlrd

def read_excel(excel_file_path):
    print("read excel: " + str(excel_file_path))
    readfile = xlrd.open_workbook(excel_file_path)
    names = readfile.sheet_names()
    obj_sheet = readfile.sheet_by_name(names[0])
    row = obj_sheet.nrows
    # col = obj_sheet.ncols
    result = [0 for i in range(row)]
    for i in range(row):
        result[i] = obj_sheet.row_values(i)
    return result

def get_id_list(filepath, primary_key_column):
    print(str(datetime.datetime.now()) + " method get_id_list() invoked.")
    
    file_arrary = read_excel(filepath)
    data_row_num = len(file_arrary)
    id_list = []
    for i in range(1, data_row_num):
        id_list.append(file_arrary[i][ord(primary_key_column) - ord('A')])
    print(str(datetime.datetime.now()) + "file: " + filepath + ", id list:" + str(id_list))
    return id_list

def get_operation_list(yesterday_filepath, 
                     today_filepath,
                     yesterday_primary_key_column,
                     today_primary_key_column):
    yesterday_id_list = get_id_list(yesterday_filepath, yesterday_primary_key_column)
    today_id_list = get_id_list(today_filepath, today_primary_key_column)
    to_add = []
    to_del = []
    to_update = []
    operationList = [yesterday_id_list, today_id_list, to_add, to_del, to_update]
    for i in range(len(yesterday_id_list)):
        is_exist_in_today = 0
        curr_yesterday_id = yesterday_id_list[i]
        for j in range(len(today_id_list)):
            if curr_yesterday_id == today_id_list[j]:
                if curr_yesterday_id not in to_update:
                    to_update.append(curr_yesterday_id)
                    is_exist_in_today = 1
                    break
        if is_exist_in_today == 0:
            if curr_yesterday_id not in to_del:
                to_del.append(curr_yesterday_id)
        is_exist_in_today = 0    #reset status
    
    for i in range(len(today_id_list)):
        curr_today_id = today_id_list[i]
        if curr_today_id not in yesterday_id_list:
            if curr_today_id not in to_add:
                to_add.append(curr_today_id)
    print("operationList: \nyesterday_id_list," + str(operationList[0])
                    + ",\ntoday_id_list" + str(operationList[1])
                    + ",\nto_add" + str(operationList[2]) 
                    + ",\nto_del" +  str(operationList[3]) 
                    + ",\nto_update" +  str(operationList[4]))
    return operationList


def get_status_by_id(id, primary_key_column, status_column, total_result):
    for i in range(1, len(total_result)):
        if id == total_result[i][ord(primary_key_column) - ord('A')]:
            return total_result[i][ord(status_column) - ord('A')]
    return "N/A"

def read_configurations(configuration_filepath):
    #configuration.txt内容例子
    # yesterday=F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\yesterday.xlsx
    # today=F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\today.xlsx
    # report=F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\report.csv
    # yesterday_primary_key_column=D
    # yesterday_status_column=E
    # today_primary_key_column=F
    # today_status_column=E
    # today_mapping_yesterday=C:B,D:C,F:D,E:E,H:F,I:G,J:H,K:I,L:J,M:K
    print("configuration filepath:" + configuration_filepath)
    configuration_file = open(configuration_filepath, mode='r')
    lines = configuration_file.readlines()
    configurations = {}
    for line in lines:
        entry = line.strip().split("=")
        if "," in entry[1]:
            # today_mapping_yesterday
            mapping_entry_array = entry[1].split(",")
            today_mapping_yesterday = {}
            for mapping_entry in mapping_entry_array:
                mapping_key_value = mapping_entry.split(":")
                today_mapping_yesterday[mapping_key_value[0]] = mapping_key_value[1]
            configurations[entry[0]] = today_mapping_yesterday
        else :
            configurations[entry[0]] = entry[1]
    return configurations

def generate_today_report(configuration_filepath):
    yesterday = "F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\yesterday.xlsx"
    # today = "F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\today.xlsx"
    # report = "F:\\projects\\daily_merge\\test_files\\scene1_no_diff\\report.csv"
    # yesterday_primary_key_column = 'D'
    # yesterday_status_column = 'E'
    # today_primary_key_column = 'F'
    # today_status_column = 'E'
    # today_mapping_yesterday = {'C':'B',
    #                            'D':'C',
    #                            'F':'D',
    #                            'E':'E',
    #                            'H':'F',
    #                            'I':'G',
    #                            'J':'H',
    #                            'K':'I',
    #                            'L':'J',
    #                            'M':'K'}
    configurations = read_configurations(configuration_filepath)
    today = configurations['today']
    report = configurations['report']
    yesterday_primary_key_column = configurations['yesterday_primary_key_column']
    yesterday_status_column = configurations['yesterday_status_column']
    today_primary_key_column = configurations['today_primary_key_column']
    today_status_column = configurations['today_status_column']
    today_mapping_yesterday = configurations['today_mapping_yesterday']

    yesterday_result = read_excel(yesterday)
    today_result = read_excel(today)
    operation_list = get_operation_list(yesterday, today, yesterday_primary_key_column, today_primary_key_column)

    try:
        report_file = open(report, mode='w')
        #write title
        for i in range(len(yesterday_result[0])):
            report_file.write(yesterday_result[0][i])    
            report_file.write(",")
        report_file.write("Tag")
        report_file.write("\n")
        #write content
        for i in range(1, len(today_result)):
            id = operation_list[1][i - 1]
            if id in operation_list[2]:
                #add
                #extract for report according by column index mapping
                to_add_report_record = []
                for x in range(len(yesterday_result[0])):
                    to_add_report_record.append("")
                
                for j in range(len(today_result[i])):
                    current_today_column = chr(j + ord('A'))
                    if current_today_column in today_mapping_yesterday:
                        to_add_report_record[ord(today_mapping_yesterday[current_today_column]) - ord('A')] = today_result[i][j]
                #write to report 
                for m in range(len(to_add_report_record)):
                    report_file.write(str(to_add_report_record[m]))
                    report_file.write(",")
                report_file.write("to add")
                report_file.write("\n")
        for i in range(1, len(yesterday_result)):
            id = operation_list[0][i - 1]
            if id in operation_list[3]:
                #delete
                for j in range(len(yesterday_result[i])):
                    report_file.write(str(yesterday_result[i][j]))
                    report_file.write(",")
                report_file.write("to delete")
            else :
                #update
                for j in range(len(yesterday_result[i])):
                    today_status = get_status_by_id(id, today_primary_key_column, today_status_column, today_result)
                    if j == ord(yesterday_status_column) - ord('A'):
                        report_file.write(today_status)
                    else :
                        report_file.write(str(yesterday_result[i][j]))
                    report_file.write(",")
                report_file.write("to update")
            report_file.write("\n")
    except Exception as e:
        print("failed to generate report.")
        print(e)
    finally:
        report_file.close()
    print("generate report successfully.")
    return
print("==^^==^^==")
if len(sys.argv) <= 1:
    print("please input the configuration filepath when running this python file.")
else :
    generate_today_report(sys.argv[1])
print("==^^==^^==")

3 参考资料

解决python中XLRDError: Excel xlsx file; not supported
https://blog.csdn.net/qq_53464193/article/details/128407954
VSCode使用 - 搭建python运行调试环境
https://zhuanlan.zhihu.com/p/625844895?utm_id=0&wd=&eqid=b12208f700185aeb000000036498f302
Python读取Excel文件
https://blog.csdn.net/weixin_49895216/article/details/127812149
python操作Excel读写–使用xlrd
https://blog.csdn.net/qq_36396104/article/details/77875703

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1064325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

信息学奥赛一本通-编程启蒙3330:【例56.1】 和为给定数

3330&#xff1a;【例56.1】 和为给定数 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 625 通过数: 245 【题目描述】 现给出若干个整数&#xff0c;询问其中是否有一对数的和等于给定的数。 【输入】 共三行&#xff1a; 第一行是整数nn(0<n≤100,000)&…

指数分布优化器(EDO)(含MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

局部放电发生的现象特点以及解决方案

局部放电发生的现象特点&#xff1a;   1、局部放电是局部过热&#xff0c;电器元件和机械元件老化的预兆&#xff1b;   2、局部放电趋势是局放随着时间的上升指数&#xff0c;这是个曲折的过程&#xff0c;某个阶段可能下降&#xff0c;但某个阶段上升&#xff1b;   3…

C# - Opencv应用(1) 之VS下环境配置详解

C# - Opencv应用&#xff08;1&#xff09; 之VS下环境配置详解 有时候&#xff0c;单纯c#做前端时会联合C实现的dll来落地某些功能由于有时候会用C - Opencv实现算法后封装成dll&#xff0c;但是有时候会感觉麻烦&#xff0c;不如直接通过C#直接调用Opencv在此慢慢总结下C# -…

练[极客大挑战 2019]RCE ME

[极客大挑战 2019]RCE ME 文章目录 [极客大挑战 2019]RCE ME掌握知识解题思路关键paylaod 掌握知识 ​ RCE无数字和字母的bypass&#xff0c;取反 异或 递增 解题思路 打开题目链接&#xff0c;发现是代码审计的题目&#xff0c;而且代码比较简单&#xff0c;似乎关键就是RC…

一个很愚蠢的游戏(中)!!!

系列文章目录 c小游戏_睡觉觉觉得的博客-CSDN博客一个很愚蠢的游戏(上)&#xff01;&#xff01;&#xff01;_睡觉觉觉得的博客-CSDN博客 文章目录 系列文章目录前言一、个人名片二、描述三、代码1.代码 总结 前言 无 &#xff08;嘻嘻&#xff09; 一、个人名片 个人主页&a…

[NewStarCTF 2023 公开赛道] week1

最近没什么正式比赛&#xff0c;都是入门赛&#xff0c;有moectf,newstar,SHCTF,0xGame都是漫长的比赛。一周一堆制。 这周newstar第1周结束了&#xff0c;据说py得很厉害&#xff0c;第2周延期了&#xff0c;什么时候开始还不一定&#xff0c;不过第一周已经结束提交了&#…

python --在2x2的子图中绘制三个子图,并使第三个子图居中

python – 在2x2的子图中绘制三个子图&#xff0c;并使第三个子图居中 基于python&#xff0c;绘制一个2x2的子图范围&#xff0c;但是只显示3个子图&#xff0c;并使得第三个子图居中显示’ 思路&#xff1a; 建立一个2x2的子图前两个正常画&#xff0c;其中第三个子图跨越两…

[开源项目推荐]privateGPT使用体验和修改

文章目录 一.跑通简述二.解读ingest.py1.导入库和读取环境变量2.文档加载3.文档处理&#xff08;调用文件加载函数和文本分割函数&#xff09; 三.injest.py效果演示1.main函数解读2.测试 四.修改代码&#xff0c;使之适配多知识库需求1.修改配置文件&#xff1a;constants.py2…

H桥级联型五电平三相逆变器Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

天线基础知识概述

一、天线方向图(一) 图1 天线方向图的辐射能量 辐射能量完全集中在天线方向图的主瓣。这样就不会有副瓣。所有的辐射能量都在天线的半功率波束宽度内。在这些−3dB边界之外,没有能量辐射。在−3dB范围内,能量分布均匀。为了能够对天线进行计算,通常会对计算进行一些简化甚…

MATLAB中syms函数使用

目录 语法 说明 示例 创建符号标量变量 创建符号标量变量的向量 创建符号标量变量矩阵 管理符号标量变量的假设 创建和评估符号函数 syms函数的作用是创建符号标量和函数&#xff0c;以及矩阵变量和函数。 语法 syms var1 ... varN syms var1 ... varN [n1 ... nM] …

VBA_MF系列技术资料1-197

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

剑指offer——JZ27 二叉树的镜像 解题思路与具体代码【C++】

一、题目描述与要求 二叉树的镜像_牛客题霸_牛客网 (nowcoder.com) 题目描述 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。 数据范围&#xff1a;二叉树的节点数 0≤n≤1000 &#xff0c; 二叉树每个节点的值 0≤val≤1000 要求&#xff1a; 空间复杂度 O(n) …

批量输出生成宗地图斑界址点成果表,支持自动分页,纯FME实现

目录 一、实现效果 二、实现过程 1.图斑转点 2.设置界址点号 3.计算界址点输出Excel的位置 4.计算边长 5.提取每页最后一个界址点 6.设置界址点成果表其他信息 7.输出Excel 三、总结 制作图斑界址点成果表是经常遇到的工作&#xff0c;除了要输出界址点坐标&#xff…

Docker基本操作【一篇学会项目部署】

文章目录 一、Docker简介二、Docker安装三、配置镜像加速四、Docker部署五、Docker基础操作1. 常见命令2. 操作演示3. 数据卷①nginx的html目录挂载②分析匿名数据卷③MySQL的本地目录挂载 4. 自定义镜像①Dockerfile②构建镜像 5. 网络①常见命令②自定义网络 六、DockerCompo…

五种雷达波束模式简介及其应用场景

图1 雷达天线方向图一览 一、铅笔光束——Pencil beam: 方位角和仰角都很窄的光束&#xff08;像铅笔一样细&#xff09;&#xff1b;用于三维雷达&#xff0c;如仪表雷达、天气雷达和防空雷达。 二、扇形波束——Fan beam 方位角非常窄&#xff08;接近1至2&#xff09;&am…

Spring框架数据访问

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

机器学习:随机森林

集成学习 集成学习&#xff08;Ensemble Learning&#xff09;是一种机器学习方法&#xff0c;通过将多个基本学习算法的预测结果进行组合&#xff0c;以获得更好的预测性能。集成学习的基本思想是通过结合多个弱分类器或回归器的预测结果&#xff0c;来构建一个更强大的集成模…

《Spring框架前世今生》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…