# 工资明细转换工具 - 使用和维护指南 | |||||
## 快速开始 | |||||
1. 确保已安装 Python 3.7 或更高版本 | |||||
2. 创建虚拟环境并安装依赖: | |||||
``` | |||||
cd excel_converter | |||||
uv venv | |||||
.venv\Scripts\activate # Windows | |||||
uv pip install -r requirements.txt | |||||
``` | |||||
3. 运行应用程序: | |||||
``` | |||||
python main.py | |||||
``` | |||||
或直接双击 `run.bat` 文件 | |||||
## 目录结构 | |||||
``` | |||||
excel_converter/ | |||||
├── app.py # 主应用程序代码 | |||||
├── config.py # 配置文件 | |||||
├── main.py # 入口点 | |||||
├── requirements.txt # 依赖列表 | |||||
├── run.bat # Windows 运行脚本 | |||||
├── README.md # 项目说明 | |||||
├── INSTRUCTIONS.md # 使用和维护指南 | |||||
└── test_data/ # 测试数据目录 | |||||
├── README.md # 测试数据说明 | |||||
└── sample_format.md # 示例格式文档 | |||||
``` | |||||
## 配置指南 | |||||
### 修改模板路径 | |||||
如果需要更改模板文件路径,请编辑 `config.py` 文件中的 `TEMPLATE_PATH` 变量。 | |||||
### 修改单元格映射关系 | |||||
单元格映射关系在 `config.py` 文件中的 `CELL_MAPPINGS` 字典中定义。格式为: | |||||
```python | |||||
{ | |||||
(源文件sheet索引, 行, 列): (目标文件sheet索引, 行, 列) | |||||
} | |||||
``` | |||||
例如,要添加新的映射,可以添加新的键值对: | |||||
```python | |||||
(0, 5, 3): (0, 5, 5) # 源文件Sheet1的C5映射到目标文件Sheet1的E5 | |||||
``` | |||||
### 修改公司和银行列表 | |||||
编辑 `config.py` 文件中的 `COMPANY_OPTIONS` 和 `BANK_OPTIONS` 列表即可添加或删除选项。 | |||||
## 常见问题解决 | |||||
### 问题1: 程序启动失败 | |||||
- 检查 Python 版本是否兼容 (3.7+) | |||||
- 确认所有依赖已正确安装 | |||||
- 检查模板文件是否存在于指定路径 | |||||
### 问题2: 转换后的文件格式不正确 | |||||
- 确认模板文件格式无误 | |||||
- 检查输入文件是否符合要求的格式 | |||||
- 确认映射关系配置正确 | |||||
### 问题3: 无法识别日期 | |||||
如果程序无法正确识别日期格式,可能需要在 `app.py` 的 `process_file` 方法中添加更多的日期解析逻辑,支持不同的日期格式。 | |||||
## 维护和扩展 | |||||
### 添加新功能 | |||||
如需添加新功能,请考虑以下几点: | |||||
1. 尽量将配置参数放在 `config.py` 文件中 | |||||
2. 保持用户界面简洁直观 | |||||
3. 添加适当的错误处理和用户反馈 | |||||
### 代码维护 | |||||
- 定期更新依赖包版本 | |||||
- 如果更改了核心功能,请更新文档 | |||||
- 考虑添加单元测试以确保功能正常 | |||||
## 联系与支持 | |||||
如有问题或需要支持,请联系项目维护者。 |
# 工资明细转换工具 | |||||
这是一个用于批量转换Excel工资明细表的图形界面工具。 | |||||
## 功能特点 | |||||
1. 批量导入Excel文件并根据模板进行转换 | |||||
2. 自定义设置每个文件的公司、银行和其他信息 | |||||
3. 按照指定的单元格映射规则转换数据 | |||||
4. 自动生成包含员工姓名和日期的输出文件名 | |||||
5. 支持复制和保留原始Excel的格式和样式 | |||||
## 环境要求 | |||||
- Python 3.7 或更高版本 (注:由于兼容性限制,不支持Python 3.2) | |||||
- 依赖包:pandas, openpyxl, xlrd, xlwt | |||||
## 关于Python 3.2兼容性说明 | |||||
由于以下原因,此工具不支持Python 3.2: | |||||
1. pandas 库需要 Python 3.7 或更高版本 | |||||
2. openpyxl 对Python 3.2 的支持有限 | |||||
3. tkinter 在 Python 3.2 中存在的一些兼容性问题 | |||||
建议使用Python 3.7或更高版本运行此工具。 | |||||
## 安装说明 | |||||
1. 确保已安装Python环境(3.7或更高版本) | |||||
2. 使用uv创建虚拟环境: | |||||
```bash | |||||
uv venv | |||||
``` | |||||
3. 激活虚拟环境: | |||||
```bash | |||||
# Windows | |||||
.venv\Scripts\activate | |||||
# macOS/Linux | |||||
source .venv/bin/activate | |||||
``` | |||||
4. 安装依赖包: | |||||
```bash | |||||
uv pip install -r requirements.txt | |||||
``` | |||||
## 使用方法 | |||||
1. 运行程序 (有多种方式): | |||||
```bash | |||||
# 方法1: 直接运行Python脚本 | |||||
python main.py | |||||
# 方法2: 使用批处理文件 (Windows) | |||||
run.bat | |||||
``` | |||||
2. 在界面上点击"选择Excel文件"按钮选择要转换的Excel文件 | |||||
3. 双击列表中的每个文件,设置公司信息(C2)、银行信息(B30)和其他信息(F2) | |||||
4. 点击"选择导出位置"按钮选择输出文件保存位置 | |||||
5. 点击"开始转换"按钮进行批量转换 | |||||
6. 转换完成后会显示成功转换的文件数量 | |||||
## 文件命名规则 | |||||
输出文件名格式为:`YYYY年M月份給料明細書-姓名.xls` | |||||
- 年份(YYYY):从输入文件第二个Sheet页的B4单元格中提取 | |||||
- 月份(M):从输入文件第二个Sheet页的B4单元格中提取 | |||||
- 姓名:从输入文件第一个Sheet页的C3单元格中提取 | |||||
## 单元格映射规则 | |||||
导入文件的第一个Sheet页映射到导出文件的第一个Sheet页: | |||||
- C3 → E2 | |||||
- D3 → E3 | |||||
- B3 → C3 | |||||
导入文件的第二个Sheet页完整复制到导出文件的第二个Sheet页,并命名为"M月勤怠一覧" | |||||
## 自定义配置 | |||||
工具的配置参数可在 `config.py` 文件中修改,包括: | |||||
- 模板文件路径 | |||||
- 单元格映射关系 | |||||
- 公司和银行选项 | |||||
- 输出文件名格式 |
[ | |||||
{ | |||||
"employee_name": "杜云", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "一三八(普通)2192640", | |||||
"account_holder": "杜云 ト ウン" | |||||
}, | |||||
{ | |||||
"employee_name": "範慶博", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "新宿通支店661(普通)8324403", | |||||
"account_holder": "範慶博 ハン ケイハク" | |||||
}, | |||||
{ | |||||
"employee_name": "龚丽犀", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "武蔵関支店(普通)6992252", | |||||
"account_holder": "龚丽犀 キヨウ レイサイ" | |||||
}, | |||||
{ | |||||
"employee_name": "劉紅軍", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "西川口支店(289)(普通)1409435", | |||||
"account_holder": "劉紅軍 リュウ コウグン" | |||||
}, | |||||
{ | |||||
"employee_name": "欧阳冠英", | |||||
"bank_name": "楽天銀行", | |||||
"branch_account": "〇五八(普通)9357044", | |||||
"account_holder": "欧阳 冠英 オウヤン グアンイン" | |||||
}, | |||||
{ | |||||
"employee_name": "孙文岱", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "一三八店(普通)1280916", | |||||
"account_holder": "孙文岱 ソン ブンタイ" | |||||
}, | |||||
{ | |||||
"employee_name": "王磊", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "町屋支店(228)(普通)6919966", | |||||
"account_holder": "王磊 オウ ライ" | |||||
}, | |||||
{ | |||||
"employee_name": "魏强", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "〇一八(普通)8654986", | |||||
"account_holder": "魏强 ギ キョウ" | |||||
}, | |||||
{ | |||||
"employee_name": "吴桐宇", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "心斎橋支店(031)(普通)0391875", | |||||
"account_holder": "吴桐宇 ゴ トンウ" | |||||
}, | |||||
{ | |||||
"employee_name": "朱文娟", | |||||
"bank_name": "楽天銀行", | |||||
"branch_account": "フーガ支店(220)(普通)1943194", | |||||
"account_holder": "朱文娟 シュ ブンケン" | |||||
}, | |||||
{ | |||||
"employee_name": "查干", | |||||
"bank_name": "りそな銀行", | |||||
"branch_account": "竹ノ塚支店(605)(普通) 4978660", | |||||
"account_holder": "査干 チャ カン" | |||||
}, | |||||
{ | |||||
"employee_name": "徐芮", | |||||
"bank_name": "三菱東京UFJ銀行", | |||||
"branch_account": "(普通)0314135", | |||||
"account_holder": "徐芮 ジョ リ" | |||||
}, | |||||
{ | |||||
"employee_name": "郑博", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "白山支店(228)(普通)6836322", | |||||
"account_holder": "鄭博 テイ ハク" | |||||
}, | |||||
{ | |||||
"employee_name": "周喻", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "日暮里之店(180)(普通)0281831", | |||||
"account_holder": "周喻 シュウ ユ" | |||||
} | |||||
] |
[] |
# Excel 转换工具配置文件 | |||||
import os | |||||
import json | |||||
# 模板文件路径 | |||||
TEMPLATE_PATH = "template.xlsx" | |||||
# 配置文件路径 | |||||
CONFIG_DIR = os.path.dirname(os.path.abspath(__file__)) | |||||
EMPLOYEE_CONFIG_PATH = os.path.join(CONFIG_DIR, "employee_info.json") | |||||
COMPANY_CONFIG_PATH = os.path.join(CONFIG_DIR, "company_options.json") # 保留兼容性 | |||||
BANK_CONFIG_PATH = os.path.join(CONFIG_DIR, "bank_options.json") # 保留兼容性 | |||||
# 单元格映射关系(源文件位置 -> 目标文件位置) | |||||
# 格式:{(源文件sheet索引, 行, 列): (目标文件sheet索引, 行, 列)} | |||||
CELL_MAPPINGS = { | |||||
# 第一个Sheet的映射关系 | |||||
(0, 3, 3): (0, 2, 5), # C3 -> E2 氏名 | |||||
(0, 3, 4): (0, 3, 5), # D3 -> E3 労働日数 | |||||
(0, 3, 2): (0, 3, 3), # B3 -> C3 ID | |||||
(0, 3, 5): (0, 6, 4), # E3 -> D6 基本給 | |||||
(0, 3, 6): (0, 7, 4), # F3 -> D7 職務給 | |||||
(0, 3, 7): (0, 8, 4), # G3 -> D8 資格手当 | |||||
(0, 3, 8): (0, 9, 4), # H3 -> D9 住宅手当 | |||||
(0, 3, 9): (0, 10, 4), # I3 -> D10 能力手当 | |||||
(0, 3, 10): (0, 11, 4), # J3 -> D11 通勤手当 | |||||
(0, 3, 11): (0, 12, 4), # K3 -> D12 残業(固定) | |||||
(0, 3, 12): (0, 13, 4), # L3 -> D13 | |||||
(0, 3, 13): (0, 14, 4), # M3 -> D14 | |||||
(0, 3, 15): (0, 17, 4), # O3 -> D17 | |||||
(0, 3, 16): (0, 18, 4), # P3 -> D18 | |||||
(0, 3, 17): (0, 19, 4), # Q3 -> D19 | |||||
(0, 3, 18): (0, 20, 4), # R3 -> D20 | |||||
(0, 3, 19): (0, 21, 4), # S3 -> D21 | |||||
(0, 3, 20): (0, 22, 4), # T3 -> D22 | |||||
(0, 3, 25): (0, 25, 5), # Y3 -> E25 | |||||
} | |||||
# 自定义值的单元格位置 | |||||
CUSTOM_CELLS = { | |||||
"company": (0, 2, 3), # C2 - 所属公司 | |||||
"bank": (0, 29, 2), # B29 - 转账银行 | |||||
"other": (0, 2, 6), # F2 - 其他信息 | |||||
} | |||||
# 文件名提取信息 | |||||
FILENAME_CONFIG = { | |||||
"name_cell": (0, 3, 3), # Sheet1 的 C3 - 员工姓名 | |||||
"year_month_cell": (1, 4, 2), # Sheet2 的 B4 - 年月信息 | |||||
} | |||||
# 第二个Sheet的命名格式 | |||||
SHEET2_NAME_FORMAT = "{month}月勤怠一覧" | |||||
# 输出文件名格式 | |||||
OUTPUT_FILENAME_FORMAT = "{year}年{month}月份給料明細書-{name}.xlsx" | |||||
# 默认选项列表(仅在配置文件不存在时使用) | |||||
DEFAULT_COMPANY_OPTIONS = [] | |||||
# 银行信息默认结构 - 扩展为字典格式,包含更多字段 | |||||
DEFAULT_BANK_OPTIONS = [ | |||||
# 银行信息示例: | |||||
# { | |||||
# "employee_name": "田中太郎", # 员工姓名 | |||||
# "bank_name": "三井住友銀行", # 银行名称 | |||||
# "branch_account": "新宿通支店661 普通 8324403", # 支店和账号 | |||||
# "account_holder": "田中太郎" # 账户持有人 | |||||
# } | |||||
] | |||||
# 员工信息默认结构 - 合并公司和银行信息 | |||||
DEFAULT_EMPLOYEE_INFO = [ | |||||
# 员工信息示例: | |||||
# { | |||||
# "employee_name": "田中太郎", # 员工姓名 | |||||
# "bank_name": "三井住友銀行", # 银行名称 | |||||
# "branch_account": "新宿通支店661 普通 8324403", # 支店和账号 | |||||
# "account_holder": "田中太郎", # 账户持有人 | |||||
# "company_name": "SPD株式会社" # 所属公司 | |||||
# } | |||||
] | |||||
# 加载员工信息 | |||||
def load_employee_info(): | |||||
# 检查是否存在员工信息配置 | |||||
if os.path.exists(EMPLOYEE_CONFIG_PATH): | |||||
try: | |||||
with open(EMPLOYEE_CONFIG_PATH, 'r', encoding='utf-8') as f: | |||||
employee_info = json.load(f) | |||||
except Exception as e: | |||||
print(f"加载员工信息出错: {e}") | |||||
employee_info = DEFAULT_EMPLOYEE_INFO | |||||
else: | |||||
# 如果不存在,尝试从旧的配置中导入 | |||||
employee_info = [] | |||||
company_options = [] | |||||
bank_options = [] | |||||
# 加载旧的公司配置 | |||||
if os.path.exists(COMPANY_CONFIG_PATH): | |||||
try: | |||||
with open(COMPANY_CONFIG_PATH, 'r', encoding='utf-8') as f: | |||||
company_options = json.load(f) | |||||
except Exception as e: | |||||
print(f"加载公司配置出错: {e}") | |||||
# 加载旧的银行配置 | |||||
if os.path.exists(BANK_CONFIG_PATH): | |||||
try: | |||||
with open(BANK_CONFIG_PATH, 'r', encoding='utf-8') as f: | |||||
bank_options = json.load(f) | |||||
# 兼容旧版本:如果是字符串列表,转换为字典 | |||||
if bank_options and isinstance(bank_options[0], str): | |||||
new_bank_options = [] | |||||
for bank_name in bank_options: | |||||
new_bank_options.append({ | |||||
"employee_name": "", | |||||
"bank_name": bank_name, | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}) | |||||
bank_options = new_bank_options | |||||
except Exception as e: | |||||
print(f"加载银行配置出错: {e}") | |||||
# 合并旧配置 | |||||
if bank_options and isinstance(bank_options[0], dict): | |||||
for bank_option in bank_options: | |||||
employee_name = bank_option.get("employee_name", "") | |||||
if employee_name: # 如果有员工姓名,则添加为一条记录 | |||||
employee_info.append({ | |||||
"employee_name": employee_name, | |||||
"bank_name": bank_option.get("bank_name", ""), | |||||
"branch_account": bank_option.get("branch_account", ""), | |||||
"account_holder": bank_option.get("account_holder", ""), | |||||
"company_name": company_options[0] if company_options else "" | |||||
}) | |||||
# 保存新的员工信息 | |||||
save_options(EMPLOYEE_CONFIG_PATH, employee_info) | |||||
return employee_info | |||||
# 保存选项 | |||||
def save_options(config_path, options): | |||||
try: | |||||
with open(config_path, 'w', encoding='utf-8') as f: | |||||
json.dump(options, f, ensure_ascii=False, indent=4) | |||||
return True | |||||
except Exception as e: | |||||
print(f"保存配置出错: {e}") | |||||
return False | |||||
# 加载选项 | |||||
EMPLOYEE_INFO = load_employee_info() | |||||
COMPANY_OPTIONS = [info.get("company_name") for info in EMPLOYEE_INFO if info.get("company_name")] | |||||
COMPANY_OPTIONS = list(set(COMPANY_OPTIONS)) # 去重 | |||||
BANK_OPTIONS = [info for info in EMPLOYEE_INFO] # 兼容性:旧代码可能仍使用BANK_OPTIONS |
[ | |||||
{ | |||||
"employee_name": "杜云", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "一三八(普通)2192640", | |||||
"account_holder": "杜云 ト ウン", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "範慶博", | |||||
"company_name": "開元株式会社", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "新宿通支店661(普通)8324403", | |||||
"account_holder": "範慶博 ハン ケイハク" | |||||
}, | |||||
{ | |||||
"employee_name": "龚丽犀", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "武蔵関支店(普通)6992252", | |||||
"account_holder": "龚丽犀 キヨウ レイサイ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "劉紅軍", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "西川口支店(289)(普通)1409435", | |||||
"account_holder": "劉紅軍 リュウ コウグン", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "欧阳冠英", | |||||
"bank_name": "楽天銀行", | |||||
"branch_account": "〇五八(普通)9357044", | |||||
"account_holder": "欧阳 冠英 オウヤン グアンイン", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "孙文岱", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "一三八店(普通)1280916", | |||||
"account_holder": "孙文岱 ソン ブンタイ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "王磊", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "町屋支店(228)(普通)6919966", | |||||
"account_holder": "王磊 オウ ライ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "魏强", | |||||
"bank_name": "ゆうちょ銀行", | |||||
"branch_account": "〇一八(普通)8654986", | |||||
"account_holder": "魏强 ギ キョウ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "吴桐宇", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "心斎橋支店(031)(普通)0391875", | |||||
"account_holder": "吴桐宇 ゴ トンウ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "朱文娟", | |||||
"bank_name": "楽天銀行", | |||||
"branch_account": "フーガ支店(220)(普通)1943194", | |||||
"account_holder": "朱文娟 シュ ブンケン", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "查干", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "りそな銀行", | |||||
"branch_account": "竹ノ塚支店(605)(普通) 4978660", | |||||
"account_holder": "査干 チャ カン" | |||||
}, | |||||
{ | |||||
"employee_name": "徐芮", | |||||
"bank_name": "三菱東京UFJ銀行", | |||||
"branch_account": "(普通)0314135", | |||||
"account_holder": "徐芮 ジョ リ", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "郑博", | |||||
"bank_name": "三井住友銀行", | |||||
"branch_account": "白山支店(228)(普通)6836322", | |||||
"account_holder": "鄭博 テイ ハク", | |||||
"company_name": "SPD株式会社" | |||||
}, | |||||
{ | |||||
"employee_name": "周喻", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "三菱UFJ銀行", | |||||
"branch_account": "日暮里之店(180)(普通)0281831", | |||||
"account_holder": "周喻 シュウ ユ" | |||||
}, | |||||
{ | |||||
"employee_name": "呉恵宜", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "西本真衣", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "柳顺子", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "宓存行", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "盖雪梅", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "王玥倩", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "周锋", | |||||
"company_name": "嘉年華株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
}, | |||||
{ | |||||
"employee_name": "西本智子", | |||||
"company_name": "SPD株式会社", | |||||
"bank_name": "", | |||||
"branch_account": "", | |||||
"account_holder": "" | |||||
} | |||||
] |
import os | |||||
import sys | |||||
import tkinter as tk | |||||
from app import ExcelConverterApp | |||||
import openpyxl | |||||
from copy import copy | |||||
def main(): | |||||
""" | |||||
Main entry point for the Excel Converter application. | |||||
""" | |||||
# Create the main window | |||||
root = tk.Tk() | |||||
root.title("日本工资明细转换工具") | |||||
# Set window icon if available | |||||
if os.path.exists("icon.ico"): | |||||
root.iconbitmap("icon.ico") | |||||
# Create and run the application | |||||
app = ExcelConverterApp(root) | |||||
# Center window on screen | |||||
window_width = 800 | |||||
window_height = 600 | |||||
screen_width = root.winfo_screenwidth() | |||||
screen_height = root.winfo_screenheight() | |||||
x = (screen_width - window_width) // 2 | |||||
y = (screen_height - window_height) // 2 | |||||
root.geometry(f"{window_width}x{window_height}+{x}+{y}") | |||||
# Run the application | |||||
root.mainloop() | |||||
if __name__ == "__main__": | |||||
main() |
pandas>=1.3.0 | |||||
openpyxl>=3.0.7 | |||||
xlrd==1.2.0 | |||||
xlwt>=1.3.0 |
@echo off | |||||
echo 启动工资明细转换工具... | |||||
python app.py | |||||
pause |
# 测试数据说明 | |||||
此文件夹用于存放测试用的Excel文件。 | |||||
测试数据要求: | |||||
1. Excel文件需要有至少2个Sheet页 | |||||
2. 第一个Sheet页需要包含以下单元格: | |||||
- B3: 员工编号 | |||||
- C3: 员工姓名 | |||||
- D3: 员工部门 | |||||
3. 第二个Sheet页需要包含以下单元格: | |||||
- B4: 日期(包含年月信息) | |||||
可以准备多个不同的测试数据文件进行批量转换测试。 |
# Excel文件格式说明 | |||||
## 输入文件格式 | |||||
输入的Excel文件应包含至少2个Sheet页,格式如下: | |||||
### Sheet1 (员工信息) | |||||
| A | B | C | D | E | F | | |||||
|---|---|---|---|---|---| | |||||
| 1 | | | | | | | |||||
| 2 | | | | | | | |||||
| 3 | | 员工编号 | 员工姓名 | 员工部门 | | | |||||
| 4 | | | | | | | |||||
重要单元格: | |||||
- B3: 员工编号 (会映射到输出文件的C3) | |||||
- C3: 员工姓名 (会映射到输出文件的E2,并用于生成文件名) | |||||
- D3: 员工部门 (会映射到输出文件的E3) | |||||
### Sheet2 (考勤信息) | |||||
| A | B | C | D | E | F | | |||||
|---|---|---|---|---|---| | |||||
| 1 | | | | | | | |||||
| 2 | | | | | | | |||||
| 3 | | | | | | | |||||
| 4 | | 2024年3月1日 | | | | | |||||
| 5 | | | | | | | |||||
重要单元格: | |||||
- B4: 日期 (格式为"YYYY年M月D日"),从中提取年月用于文件命名 | |||||
整个Sheet2会完整复制到输出文件的第二个Sheet页,并重命名为"M月勤怠一覧"。 | |||||
## 输出文件格式 | |||||
输出文件基于模板文件(template.xls)生成,包含以下主要字段: | |||||
### Sheet1 (工资明细) | |||||
| A | B | C | D | E | F | | |||||
|---|---|---|---|---|---| | |||||
| 1 | | | | | | | |||||
| 2 | | | 所属公司 | | 员工姓名 | 其他信息 | | |||||
| 3 | | | 员工编号 | | 员工部门 | | | |||||
| ... | | | | | | | |||||
| 30 | | 转账银行 | | | | | |||||
自定义字段: | |||||
- C2: 所属公司 (从UI界面选择) | |||||
- B30: 转账银行 (从UI界面选择) | |||||
- F2: 其他信息 (从UI界面输入) | |||||
### Sheet2 (M月勤怠一覧) | |||||
这个Sheet页是从输入文件的Sheet2完整复制而来,保留所有内容和格式。 | |||||
## 文件命名规则 | |||||
输出文件名格式:`YYYY年M月份給料明細書-姓名.xls` | |||||
例如:`2024年3月份給料明細書-範慶博.xls` |