Spaces:
Configuration error
Configuration error
Commit
·
76b7572
0
Parent(s):
Initial commit: Quality Inspection Report Generator
Browse files- .gitignore +38 -0
- LICENSE +21 -0
- README.md +80 -0
- check_template.py +34 -0
- generate_quality_inspection_reports.py +113 -0
- quality_inspection_documentation.py +109 -0
- quick.py +61 -0
- requirements.txt +2 -0
- test_structure.py +38 -0
.gitignore
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
env/
|
| 8 |
+
build/
|
| 9 |
+
develop-eggs/
|
| 10 |
+
dist/
|
| 11 |
+
downloads/
|
| 12 |
+
eggs/
|
| 13 |
+
.eggs/
|
| 14 |
+
lib/
|
| 15 |
+
lib64/
|
| 16 |
+
parts/
|
| 17 |
+
sdist/
|
| 18 |
+
var/
|
| 19 |
+
wheels/
|
| 20 |
+
*.egg-info/
|
| 21 |
+
.installed.cfg
|
| 22 |
+
*.egg
|
| 23 |
+
|
| 24 |
+
# Excel files (since they contain data)
|
| 25 |
+
*.xls
|
| 26 |
+
*.xlsx
|
| 27 |
+
*.xlsm
|
| 28 |
+
*.xlsb
|
| 29 |
+
|
| 30 |
+
# IDE
|
| 31 |
+
.idea/
|
| 32 |
+
.vscode/
|
| 33 |
+
*.swp
|
| 34 |
+
*.swo
|
| 35 |
+
|
| 36 |
+
# OS
|
| 37 |
+
.DS_Store
|
| 38 |
+
Thumbs.db
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2024 Quality Inspection Report Generator
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Quality Inspection Report Generator
|
| 2 |
+
|
| 3 |
+
一个用于从 Excel 数据生成质量检验报告的 Python 工具。
|
| 4 |
+
|
| 5 |
+
## 功能特点
|
| 6 |
+
|
| 7 |
+
- 从源数据 Excel 文件自动生成质量检验报告
|
| 8 |
+
- 支持多个客户的批量处理
|
| 9 |
+
- 保持模板格式和样式
|
| 10 |
+
- 自动计算日期和有效期
|
| 11 |
+
- 完整的化学元素和尺寸数据处理
|
| 12 |
+
|
| 13 |
+
## 系统要求
|
| 14 |
+
|
| 15 |
+
- Python 3.6+
|
| 16 |
+
- pandas
|
| 17 |
+
- openpyxl
|
| 18 |
+
|
| 19 |
+
## 安装
|
| 20 |
+
|
| 21 |
+
1. 克隆仓库:
|
| 22 |
+
```bash
|
| 23 |
+
git clone https://github.com/1587causalai/quality-inspection-report-generator.git
|
| 24 |
+
cd quality-inspection-report-generator
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
2. 安装依赖:
|
| 28 |
+
```bash
|
| 29 |
+
pip install -r requirements.txt
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
## 使用方法
|
| 33 |
+
|
| 34 |
+
1. 准备输入文件:
|
| 35 |
+
- `1.xls`:源数据文件,包含 HEADER、Dimension 和 Sand 工作表
|
| 36 |
+
- `2.xlsx`:模板文件,包含 WACKER 工作表
|
| 37 |
+
|
| 38 |
+
2. 运行脚本:
|
| 39 |
+
```bash
|
| 40 |
+
python generate_quality_inspection_reports.py
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
3. 检查输出:
|
| 44 |
+
- 生成的报告将保存为 `2_updated.xlsx`
|
| 45 |
+
- 每个客户的数据将保存在单独的工作表中
|
| 46 |
+
|
| 47 |
+
## 数据格式要求
|
| 48 |
+
|
| 49 |
+
### 输入文件结构
|
| 50 |
+
|
| 51 |
+
1. `1.xls` 包含:
|
| 52 |
+
- HEADER:基本信息(数量、批准人等)
|
| 53 |
+
- Dimension:尺寸数据和检验日期
|
| 54 |
+
- Sand:化学元素测试数据
|
| 55 |
+
|
| 56 |
+
2. `2.xlsx` 包含:
|
| 57 |
+
- WACKER:报告模板格式
|
| 58 |
+
|
| 59 |
+
### 输出报告格式
|
| 60 |
+
|
| 61 |
+
- 基本信息(B3-D5):数量、批号、日期等
|
| 62 |
+
- 化学元素数据(D9-D19):11种元素的测试结果
|
| 63 |
+
- 尺寸数据(D20-D28):外径、高度、壁厚等
|
| 64 |
+
- 批准信息(D29):批准人姓名
|
| 65 |
+
|
| 66 |
+
## 文档
|
| 67 |
+
|
| 68 |
+
详细的代码文档请参考 `quality_inspection_documentation.py`。
|
| 69 |
+
|
| 70 |
+
## 许可证
|
| 71 |
+
|
| 72 |
+
MIT License
|
| 73 |
+
|
| 74 |
+
## 作者
|
| 75 |
+
|
| 76 |
+
[Your Name]
|
| 77 |
+
|
| 78 |
+
## 贡献
|
| 79 |
+
|
| 80 |
+
欢迎提交 Issue 和 Pull Request!
|
check_template.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from openpyxl import load_workbook
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
def print_sheet_content(file_path, sheet_name):
|
| 5 |
+
wb = load_workbook(file_path)
|
| 6 |
+
sheet = wb[sheet_name]
|
| 7 |
+
|
| 8 |
+
print(f"\nContent of sheet '{sheet_name}':")
|
| 9 |
+
for i, row in enumerate(sheet.rows, 1):
|
| 10 |
+
values = [str(cell.value) if cell.value is not None else '' for cell in row]
|
| 11 |
+
print(f"Row {i}: {values}")
|
| 12 |
+
|
| 13 |
+
# 打印模板文件的内容
|
| 14 |
+
print_sheet_content('2.xlsx', 'WACKER')
|
| 15 |
+
|
| 16 |
+
# 读取第一个文件的Sand工作表
|
| 17 |
+
print("\n原始数据结构:")
|
| 18 |
+
file1 = '1.xls'
|
| 19 |
+
df = pd.read_excel(file1, sheet_name='Sand')
|
| 20 |
+
print("\n列名:")
|
| 21 |
+
print(df.columns.tolist())
|
| 22 |
+
|
| 23 |
+
# 打印前几行数据以查看结构
|
| 24 |
+
print("\n前几行数据:")
|
| 25 |
+
print(df.head())
|
| 26 |
+
|
| 27 |
+
# 读取跳过12行的数据
|
| 28 |
+
print("\n跳过12行的数据:")
|
| 29 |
+
sand_df_skipped = pd.read_excel(file1, sheet_name='Sand', skiprows=12)
|
| 30 |
+
print(sand_df_skipped.head())
|
| 31 |
+
|
| 32 |
+
# 打印所有列名
|
| 33 |
+
print("\n跳过12行后的列名:")
|
| 34 |
+
print(sand_df_skipped.columns.tolist())
|
generate_quality_inspection_reports.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from openpyxl import load_workbook
|
| 3 |
+
from datetime import datetime, timedelta
|
| 4 |
+
|
| 5 |
+
# 读取第一个文件
|
| 6 |
+
file1 = '1.xls'
|
| 7 |
+
header_df = pd.read_excel(file1, sheet_name='HEADER')
|
| 8 |
+
|
| 9 |
+
# 读取Dimension表,跳过前12行,然后使用第13行作为列名
|
| 10 |
+
dimension_df = pd.read_excel(file1, sheet_name='Dimension', skiprows=12)
|
| 11 |
+
# 使用第一行作为列名
|
| 12 |
+
dimension_df.columns = dimension_df.iloc[0]
|
| 13 |
+
# 删除第一行(现在已经作为列名)并重置索引
|
| 14 |
+
dimension_df = dimension_df.iloc[1:].reset_index(drop=True)
|
| 15 |
+
|
| 16 |
+
# 读取Sand表的数据
|
| 17 |
+
sand_df = pd.read_excel(file1, sheet_name='Sand', header=None)
|
| 18 |
+
|
| 19 |
+
# 读取第二个文件
|
| 20 |
+
file2 = '2.xlsx'
|
| 21 |
+
wb = load_workbook(file2)
|
| 22 |
+
wacker_sheet = wb['WACKER']
|
| 23 |
+
|
| 24 |
+
# 获取Sales Order Quantity和Quality Assured By
|
| 25 |
+
sales_order_quantity = header_df.iloc[5, 2] # Sales Order Quantity位置
|
| 26 |
+
quality_assured_by = header_df.iloc[3, 7] # Quality Assured By在第4行最后一列
|
| 27 |
+
|
| 28 |
+
# 定义元素和行号的对应关系
|
| 29 |
+
element_row_mapping = {
|
| 30 |
+
'Al': 9, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Al
|
| 31 |
+
'Ca': 10, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Ca
|
| 32 |
+
'Cu': 11, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Cu
|
| 33 |
+
'Fe': 12, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Fe
|
| 34 |
+
'K': 13, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_K
|
| 35 |
+
'Li': 14, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Li
|
| 36 |
+
'Mg': 15, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Mg
|
| 37 |
+
'Mn': 16, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Mn
|
| 38 |
+
'Na': 17, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Na
|
| 39 |
+
'Ti': 18, # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Ti
|
| 40 |
+
'Zr': 19 # 硅柏_石英坩埚_QC530HS_201410_V3B-CN_Zr
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
# 定义元素在Sand表中的列索引
|
| 44 |
+
element_col_mapping = {
|
| 45 |
+
'Al': 4, # 第5列
|
| 46 |
+
'Ca': 5, # 第6列
|
| 47 |
+
'Cu': 6, # 第7列
|
| 48 |
+
'Fe': 7, # 第8列
|
| 49 |
+
'K': 8, # 第9列
|
| 50 |
+
'Li': 9, # 第10列
|
| 51 |
+
'Mg': 10, # 第11列
|
| 52 |
+
'Mn': 11, # 第12列
|
| 53 |
+
'Na': 12, # 第13列
|
| 54 |
+
'Ti': 13, # 第14列
|
| 55 |
+
'Zr': 14 # 第15列
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
# 遍历Dimension表格中的每个Customer ID
|
| 59 |
+
for index, row in dimension_df.iterrows():
|
| 60 |
+
customer_id = row['Customer ID'] # 现在这个列名应该是正确的了
|
| 61 |
+
inspection_date = pd.to_datetime(row['Inspection Date']).strftime('%Y-%m-%d') # 格式化日期
|
| 62 |
+
|
| 63 |
+
# 创建新的工作表
|
| 64 |
+
new_sheet = wb.create_sheet(title=str(customer_id))
|
| 65 |
+
|
| 66 |
+
# 复制WACKER表格的内容到新工作表(这样会保持原有的客户名称)
|
| 67 |
+
for row_wacker in wacker_sheet.iter_rows(values_only=True):
|
| 68 |
+
new_sheet.append(row_wacker)
|
| 69 |
+
|
| 70 |
+
# 填充数据(不再覆盖客户名称)
|
| 71 |
+
new_sheet['B3'] = str(sales_order_quantity) + ' PCS' # Number+Unit/数量+单位
|
| 72 |
+
new_sheet['B4'] = customer_id # Batch reference/批号
|
| 73 |
+
new_sheet['D4'] = inspection_date # Date of issue/报告日期
|
| 74 |
+
new_sheet['B5'] = inspection_date # Production date/生产日期
|
| 75 |
+
new_sheet['D5'] = (datetime.strptime(inspection_date, '%Y-%m-%d') + timedelta(days=730)).strftime('%Y-%m-%d') # Expiring date/失效日期
|
| 76 |
+
|
| 77 |
+
# 从sand表中获取当前customer_id的数据
|
| 78 |
+
sand_rows = sand_df[sand_df[2] == customer_id] # 使用第3列(索引2)作为Crucible ID
|
| 79 |
+
if not sand_rows.empty:
|
| 80 |
+
sand_row = sand_rows.iloc[0]
|
| 81 |
+
|
| 82 |
+
# 填充元素数据
|
| 83 |
+
for element, target_row in element_row_mapping.items():
|
| 84 |
+
source_col = element_col_mapping[element]
|
| 85 |
+
new_sheet[f'D{target_row}'] = sand_row[source_col]
|
| 86 |
+
|
| 87 |
+
# 填充Analysis result/分析结果
|
| 88 |
+
# 保持原有的测试项目名称,只更新分析结果列
|
| 89 |
+
for i in range(20, 29):
|
| 90 |
+
if i == 20:
|
| 91 |
+
new_sheet[f'D{i}'] = row['OD1'] # 外径1
|
| 92 |
+
elif i == 21:
|
| 93 |
+
new_sheet[f'D{i}'] = row['OD2'] # 外径2
|
| 94 |
+
elif i == 22:
|
| 95 |
+
new_sheet[f'D{i}'] = row['OD3'] # 外径3
|
| 96 |
+
elif i == 23:
|
| 97 |
+
new_sheet[f'D{i}'] = row['Height'] # 高度
|
| 98 |
+
elif i == 24:
|
| 99 |
+
new_sheet[f'D{i}'] = row['Wall11'] # 壁厚11
|
| 100 |
+
elif i == 25:
|
| 101 |
+
new_sheet[f'D{i}'] = row['Wall12'] # 壁厚12
|
| 102 |
+
elif i == 26:
|
| 103 |
+
new_sheet[f'D{i}'] = row['Wall13'] # 壁厚13
|
| 104 |
+
elif i == 27:
|
| 105 |
+
new_sheet[f'D{i}'] = row['Wall2'] # 壁厚2
|
| 106 |
+
elif i == 28:
|
| 107 |
+
new_sheet[f'D{i}'] = row['Wall3'] # 壁厚3
|
| 108 |
+
|
| 109 |
+
# 保持"批准人:"文本,并在其后添加名字
|
| 110 |
+
new_sheet['D29'] = f"批准人:{quality_assured_by}"
|
| 111 |
+
|
| 112 |
+
# 保存修改后的文件
|
| 113 |
+
wb.save('2_updated.xlsx')
|
quality_inspection_documentation.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
质量检验报告生成脚本说明文档
|
| 3 |
+
============================
|
| 4 |
+
|
| 5 |
+
本文档详细说明了 generate_quality_inspection_reports.py 的工作原理和数据处理流程。
|
| 6 |
+
|
| 7 |
+
输入文件
|
| 8 |
+
--------
|
| 9 |
+
1. 1.xls - 源数据文件,包含以下工作表:
|
| 10 |
+
- HEADER: 包含基本信息如数量和批准人
|
| 11 |
+
- Dimension: 包含尺寸数据和检验日期
|
| 12 |
+
- Sand: 包含化学元素测试数据
|
| 13 |
+
|
| 14 |
+
2. 2.xlsx - 模板文件,包含:
|
| 15 |
+
- WACKER: 模板工作表,包含预设格式
|
| 16 |
+
|
| 17 |
+
数据结构
|
| 18 |
+
--------
|
| 19 |
+
1. Sand表结构(跳过前12行后):
|
| 20 |
+
- 第3列 (索引2): Crucible ID(客户ID)
|
| 21 |
+
- 第5-15列 (索引4-14): 化学元素测试数据
|
| 22 |
+
* Al: 第5列 (索引4)
|
| 23 |
+
* Ca: 第6列 (索引5)
|
| 24 |
+
* Cu: 第7列 (索引6)
|
| 25 |
+
* Fe: 第8列 (索引7)
|
| 26 |
+
* K: 第9列 (索引8)
|
| 27 |
+
* Li: 第10列 (索引9)
|
| 28 |
+
* Mg: 第11列 (索引10)
|
| 29 |
+
* Mn: 第12列 (索引11)
|
| 30 |
+
* Na: 第13列 (索引12)
|
| 31 |
+
* Ti: 第14列 (索引13)
|
| 32 |
+
* Zr: 第15列 (索引14)
|
| 33 |
+
|
| 34 |
+
2. 输出报告结构:
|
| 35 |
+
- 基本信息(B3-D5):数量、批号、日期等
|
| 36 |
+
- 化学元素数据(D9-D19):对应11种元素的测试结果
|
| 37 |
+
- 尺寸数据(D20-D28):外径、高度、壁厚等
|
| 38 |
+
- 批准信息(D29):批准人姓名
|
| 39 |
+
|
| 40 |
+
处理流程
|
| 41 |
+
--------
|
| 42 |
+
1. 数据读取阶段:
|
| 43 |
+
- 读取HEADER表获取基本信息
|
| 44 |
+
- 读取Dimension表获取尺寸数据和日期信息
|
| 45 |
+
- 读取Sand表获取化学元素测试数据
|
| 46 |
+
- 读取模板文件作为基础格式
|
| 47 |
+
|
| 48 |
+
2. 数据处理阶段:
|
| 49 |
+
- 遍历Dimension表中的每个Customer ID
|
| 50 |
+
- 为每个Customer ID创建新的工作表
|
| 51 |
+
- 复制模板内容保持格式一致
|
| 52 |
+
- 填充基本信息(数量、日期等)
|
| 53 |
+
- 从Sand表匹配并填充化学元素数据
|
| 54 |
+
- 填充尺寸数据
|
| 55 |
+
- 添加批准人信息
|
| 56 |
+
|
| 57 |
+
3. 数据映射关系:
|
| 58 |
+
a. 元素行号映射 (element_row_mapping):
|
| 59 |
+
- Al -> 第9行
|
| 60 |
+
- Ca -> 第10行
|
| 61 |
+
- Cu -> 第11行
|
| 62 |
+
...(依此类推)
|
| 63 |
+
|
| 64 |
+
b. 元素列索引映射 (element_col_mapping):
|
| 65 |
+
- Al -> 第5列(索引4)
|
| 66 |
+
- Ca -> 第6列(索引5)
|
| 67 |
+
- Cu -> 第7列(索引6)
|
| 68 |
+
...(依此类推)
|
| 69 |
+
|
| 70 |
+
注意事项
|
| 71 |
+
--------
|
| 72 |
+
1. 日期处理:
|
| 73 |
+
- 检验日期格式化为 YYYY-MM-DD
|
| 74 |
+
- 失效日期自动计算为检验日期+730天(2年)
|
| 75 |
+
|
| 76 |
+
2. 数据验证:
|
| 77 |
+
- 检查Customer ID是否存在于Sand表中
|
| 78 |
+
- 确保所有必要的数据都被正确填充
|
| 79 |
+
|
| 80 |
+
3. 格式保持:
|
| 81 |
+
- 通过复制模板内容保持原有格式
|
| 82 |
+
- 保持"批准人:"文本的一致性
|
| 83 |
+
|
| 84 |
+
使用方法
|
| 85 |
+
--------
|
| 86 |
+
1. 确保输入文件 (1.xls 和 2.xlsx) 在正确的位置
|
| 87 |
+
2. 运行脚本:python generate_quality_inspection_reports.py
|
| 88 |
+
3. 输出文件将保存为 2_updated.xlsx
|
| 89 |
+
|
| 90 |
+
输出文件
|
| 91 |
+
--------
|
| 92 |
+
2_updated.xlsx:包含所有客户的质量检验报告,每个客户一个工作表,
|
| 93 |
+
保持了原有的格式并填充了所有必要的数据。
|
| 94 |
+
"""
|
| 95 |
+
|
| 96 |
+
# 示例:如何使用生成的报告
|
| 97 |
+
def usage_example():
|
| 98 |
+
print("使用示例:")
|
| 99 |
+
print("1. 准备输入文件:")
|
| 100 |
+
print(" - 确保有1.xls(源数据)")
|
| 101 |
+
print(" - 确保有2.xlsx(模板)")
|
| 102 |
+
print("\n2. 运行脚本:")
|
| 103 |
+
print(" python generate_quality_inspection_reports.py")
|
| 104 |
+
print("\n3. 检查输出:")
|
| 105 |
+
print(" - 查看2_updated.xlsx")
|
| 106 |
+
print(" - 验证每个客户的工作表是否正确生成")
|
| 107 |
+
|
| 108 |
+
if __name__ == "__main__":
|
| 109 |
+
usage_example()
|
quick.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
def extract_sand_data(input_file, output_file):
|
| 4 |
+
try:
|
| 5 |
+
# 读取Excel文件的Sand工作表
|
| 6 |
+
xls = pd.ExcelFile(input_file)
|
| 7 |
+
if 'Sand' not in xls.sheet_names:
|
| 8 |
+
raise ValueError("Excel文件中缺少'Sand'工作表")
|
| 9 |
+
|
| 10 |
+
# 读取Sand工作表
|
| 11 |
+
df = pd.read_excel(xls, sheet_name='Sand', header=None)
|
| 12 |
+
|
| 13 |
+
# 定义数据起始行和列索引
|
| 14 |
+
start_row = 13 # 数据从第11行开始(0-based索引)
|
| 15 |
+
crucible_id_col = 2 # Crucible ID在C列(0-based索引)
|
| 16 |
+
element_start_col = 4 # 元素数据从第5列开始(0-based索引)
|
| 17 |
+
element_end_col = 14 # 元素数据到第15列结束(0-based索引)
|
| 18 |
+
|
| 19 |
+
# 提取数据
|
| 20 |
+
results = []
|
| 21 |
+
for row_idx in range(start_row, len(df)):
|
| 22 |
+
row = df.iloc[row_idx]
|
| 23 |
+
if pd.isna(row[crucible_id_col]): # 跳过空行
|
| 24 |
+
continue
|
| 25 |
+
|
| 26 |
+
# 提取Crucible ID
|
| 27 |
+
crucible_id = str(row[crucible_id_col]).strip()
|
| 28 |
+
|
| 29 |
+
# 提取元素数据
|
| 30 |
+
elements = {
|
| 31 |
+
"Crucible ID": crucible_id,
|
| 32 |
+
"Al": row[element_start_col],
|
| 33 |
+
"Ca": row[element_start_col + 1],
|
| 34 |
+
"Cu": row[element_start_col + 2],
|
| 35 |
+
"Fe": row[element_start_col + 3],
|
| 36 |
+
"K": row[element_start_col + 4],
|
| 37 |
+
"Li": row[element_start_col + 5],
|
| 38 |
+
"Mg": row[element_start_col + 6],
|
| 39 |
+
"Mn": row[element_start_col + 7],
|
| 40 |
+
"Na": row[element_start_col + 8],
|
| 41 |
+
"Ti": row[element_start_col + 9],
|
| 42 |
+
"Zr": row[element_start_col + 10],
|
| 43 |
+
}
|
| 44 |
+
results.append(elements)
|
| 45 |
+
|
| 46 |
+
# 将结果转换为DataFrame
|
| 47 |
+
result_df = pd.DataFrame(results)
|
| 48 |
+
|
| 49 |
+
# 保存到新的Excel文件
|
| 50 |
+
result_df.to_excel(output_file, index=False)
|
| 51 |
+
return f"数据已成功保存到 {output_file}"
|
| 52 |
+
|
| 53 |
+
except Exception as e:
|
| 54 |
+
return f"处理错误: {str(e)}"
|
| 55 |
+
|
| 56 |
+
# 使用示例
|
| 57 |
+
if __name__ == "__main__":
|
| 58 |
+
input_file = "1.xls" # 输入文件路径
|
| 59 |
+
output_file = "output.xlsx" # 输出文件路径
|
| 60 |
+
result = extract_sand_data(input_file, output_file)
|
| 61 |
+
print(result)
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pandas>=1.3.0
|
| 2 |
+
openpyxl>=3.0.0
|
test_structure.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
def analyze_excel_structure(file_path):
|
| 4 |
+
"""分析Excel文件的基本结构"""
|
| 5 |
+
print(f"\n开始分析文件: {file_path}")
|
| 6 |
+
|
| 7 |
+
# 读取Excel文件
|
| 8 |
+
xls = pd.ExcelFile(file_path)
|
| 9 |
+
|
| 10 |
+
# 打印所有sheet名称
|
| 11 |
+
print("\n所有Sheet页:")
|
| 12 |
+
for sheet_name in xls.sheet_names:
|
| 13 |
+
print(f"- {sheet_name}")
|
| 14 |
+
|
| 15 |
+
# 分析每个sheet的结构
|
| 16 |
+
for sheet_name in xls.sheet_names:
|
| 17 |
+
print(f"\n\n分析 Sheet [{sheet_name}]:")
|
| 18 |
+
|
| 19 |
+
# 尝试不同的skiprows值来找到正确的数据结构
|
| 20 |
+
for skip_rows in [0, 6, 12]:
|
| 21 |
+
print(f"\n跳过 {skip_rows} 行后的结构:")
|
| 22 |
+
try:
|
| 23 |
+
df = pd.read_excel(file_path, sheet_name=sheet_name, skiprows=skip_rows)
|
| 24 |
+
print("\n列名:")
|
| 25 |
+
print(df.columns.tolist())
|
| 26 |
+
print("\n前3行数据:")
|
| 27 |
+
print(df.head(3))
|
| 28 |
+
|
| 29 |
+
# 打印非空行数
|
| 30 |
+
non_empty_rows = len(df.dropna(how='all'))
|
| 31 |
+
print(f"\n非空行数: {non_empty_rows}")
|
| 32 |
+
|
| 33 |
+
except Exception as e:
|
| 34 |
+
print(f"读取出错: {str(e)}")
|
| 35 |
+
|
| 36 |
+
if __name__ == "__main__":
|
| 37 |
+
INPUT_FILE = "1.xls"
|
| 38 |
+
analyze_excel_structure(INPUT_FILE)
|