first commit

This commit is contained in:
Idiot-awa
2026-06-29 15:32:32 +08:00
commit 8104abb37a
11 changed files with 1005 additions and 0 deletions
+658
View File
@@ -0,0 +1,658 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>x-data-spreadsheet</title>
<style>
body { margin:0; padding:20px; font-family:Arial,sans-serif; background-color:#f5f5f5; }
#xspreadsheet { width:100%; height:600px; box-shadow:0 2px 10px rgba(0,0,0,0.1); background-color:white; }
</style>
<link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css">
</head>
<body>
<h1>x-data-spreadsheet</h1>
<div id="xspreadsheet"></div>
<script src="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.js"></script>
<script>
const sheetData = {
"name": "Table_0",
"rows": {
"0": {
"cells": {
"19": {
"text": "PD4.2.2",
"merge": [
0,
2
]
}
}
},
"1": {
"cells": {
"0": {
"text": "基本要求",
"merge": [
0,
1
]
},
"2": {
"text": "01.在路基用地和取土坑范国内,己清除地表植被、杂物、积水、淤泥和表土,处理坑塘,并按施工技术规范和设计要求对基底进行压实.表土己充分利用.口2.坝方路基分层坝筑压实,每层表面平整,路拱合适,排水良好,无明显碾压轮迹,无亏坡.口3.己设置施工临时排水系统,避免冲刷边坡,路床顶面无积水.4.在设定取土区内合理取土,无溢开滥挖.完工后己按要求对取土坑和奔土场进行依整.",
"merge": [
0,
19
]
}
}
},
"2": {
"cells": {
"1": {
"text": "项次",
"merge": [
1,
0
]
},
"2": {
"text": "检查项目",
"merge": [
1,
3
]
},
"6": {
"text": "规定值或允许偏差",
"merge": [
0,
2
]
},
"9": {
"text": "实测值或实测差值",
"merge": [
0,
9
]
},
"19": {
"text": "质量评定",
"merge": [
0,
2
]
}
}
},
"3": {
"cells": {
"6": {
"text": "商速公路一级公路"
},
"7": {
"text": "二级公路"
},
"8": {
"text": "三、四级公路"
},
"9": {
"text": "1"
},
"10": {
"text": "2"
},
"11": {
"text": "3"
},
"12": {
"text": "4"
},
"13": {
"text": "5"
},
"14": {
"text": "6"
},
"15": {
"text": "7"
},
"16": {
"text": "8"
},
"17": {
"text": "9"
},
"18": {
"text": "10"
},
"19": {
"text": "平均值、代表值"
},
"20": {
"text": "合格率(%)"
},
"21": {
"text": "合格判定"
}
}
},
"4": {
"cells": {
"1": {
"text": "1A",
"merge": [
6,
0
]
},
"2": {
"text": "医卖医卖",
"merge": [
6,
0
]
},
"3": {
"text": "上路床",
"merge": [
0,
1
]
},
"5": {
"text": "0~0.3m"
},
"6": {
"text": "≥96"
},
"7": {
"text": "≥95"
},
"8": {
"text": "≥94"
}
}
},
"5": {
"cells": {
"3": {
"text": "下路床",
"merge": [
1,
0
]
},
"4": {
"text": "经、中及交通荷载等级"
},
"5": {
"text": "0.3m~0.8m"
},
"6": {
"text": "96"
},
"7": {
"text": "≥95"
},
"8": {
"text": "≥94"
},
"9": {
"merge": [
0,
9
]
}
}
},
"6": {
"cells": {
"4": {
"text": "特重、极重交通荷载等级"
},
"5": {
"text": "0.3m~1.2m"
},
"6": {
"text": "296"
},
"7": {
"text": "≥95"
},
"8": {
"text": "-"
}
}
},
"7": {
"cells": {
"3": {
"text": "上路提",
"merge": [
1,
0
]
},
"4": {
"text": "轻、中及重交通荷载等级"
},
"5": {
"text": "0.8m~1.5m"
},
"6": {
"text": "≥94"
},
"7": {
"text": "≥94"
},
"8": {
"text": "≥93"
}
}
},
"8": {
"cells": {
"4": {
"text": "特薰、极薰交通荷载等级"
},
"5": {
"text": "1.2m~1.9m"
},
"6": {
"text": "≥94"
},
"7": {
"text": "≥94"
},
"8": {
"text": "-"
}
}
},
"9": {
"cells": {
"3": {
"text": "下路提",
"merge": [
1,
0
]
},
"4": {
"text": "轻、中及交通荷载等级"
},
"5": {
"text": "≥1.5m"
},
"6": {
"text": "≥93",
"merge": [
1,
0
]
},
"7": {
"text": "≥92",
"merge": [
1,
0
]
},
"8": {
"text": "≥90",
"merge": [
1,
0
]
}
}
},
"10": {
"cells": {
"4": {
"text": "特、极薰交通荷载等级"
},
"5": {
"text": "≥1.9m"
}
}
},
"11": {
"cells": {
"1": {
"text": "2A"
},
"2": {
"text": "弯沉(0.01mm)",
"merge": [
0,
3
]
},
"6": {
"text": "≤设计验收弯沉值",
"merge": [
0,
2
]
},
"9": {
"merge": [
0,
9
]
}
}
},
"12": {
"cells": {
"1": {
"text": "3"
},
"2": {
"text": "纵断商程(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "+10-15"
},
"7": {
"text": "+10.-20",
"merge": [
0,
1
]
}
}
},
"13": {
"cells": {
"1": {
"text": "4"
},
"2": {
"text": "中线偏位(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "50"
},
"7": {
"text": "100",
"merge": [
0,
1
]
}
}
},
"14": {
"cells": {
"1": {
"text": "5"
},
"2": {
"text": "宽度(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "满足设计要求",
"merge": [
0,
2
]
}
}
},
"15": {
"cells": {
"1": {
"text": "6"
},
"2": {
"text": "平整度(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "415"
},
"7": {
"text": "520",
"merge": [
0,
1
]
}
}
},
"16": {
"cells": {
"1": {
"text": "7"
},
"2": {
"text": "横坡(%)",
"merge": [
0,
3
]
},
"6": {
"text": "±0.3"
},
"7": {
"text": "±0.5",
"merge": [
0,
1
]
}
}
},
"17": {
"cells": {
"1": {
"text": "8"
},
"2": {
"text": "边坡",
"merge": [
0,
3
]
},
"6": {
"text": "满足设计要求",
"merge": [
0,
2
]
}
}
},
"18": {
"cells": {
"0": {
"text": "外观质量",
"merge": [
0,
5
]
},
"6": {
"text": "01.路基边线与边坡未出现单向累计长度超过50m的弯折.口2.路基边坡、护坡道、碎离台无滑坡、爆方或深度超过100mm的冲沟.",
"merge": [
0,
8
]
},
"15": {
"text": "质量保证资料",
"merge": [
0,
3
]
}
}
},
"19": {
"cells": {
"0": {
"text": "工程质量等级评定",
"merge": [
0,
5
]
},
"6": {
"text": "口合格口不合格",
"merge": [
0,
13
]
}
}
},
"len": 20
},
"merges": [
"P19:S19",
"C17:F17",
"G19:O19",
"B3:B4",
"J12:S12",
"G18:I18",
"G3:I3",
"J3:S3",
"G10:G11",
"G15:I15",
"C13:F13",
"B5:B11",
"C18:F18",
"T1:V1",
"C15:F15",
"A20:F20",
"C14:F14",
"H17:I17",
"A2:B2",
"H16:I16",
"A19:F19",
"D8:D9",
"C16:F16",
"T3:V3",
"G12:I12",
"C2:V2",
"H13:I13",
"I10:I11",
"J6:S6",
"C5:C11",
"D10:D11",
"C3:F4",
"G20:T20",
"C12:F12",
"D5:E5",
"H14:I14",
"D6:D7",
"H10:H11"
],
"cols": {
"0": {
"width": 120
},
"1": {
"width": 120
},
"2": {
"width": 120
},
"3": {
"width": 120
},
"4": {
"width": 120
},
"5": {
"width": 120
},
"6": {
"width": 120
},
"7": {
"width": 120
},
"8": {
"width": 120
},
"9": {
"width": 120
},
"10": {
"width": 120
},
"11": {
"width": 120
},
"12": {
"width": 120
},
"13": {
"width": 120
},
"14": {
"width": 120
},
"15": {
"width": 120
},
"16": {
"width": 120
},
"17": {
"width": 120
},
"18": {
"width": 120
},
"19": {
"width": 120
},
"20": {
"width": 120
},
"21": {
"width": 120
}
}
};
document.addEventListener('DOMContentLoaded', function () {
if (typeof x_spreadsheet === 'undefined') {
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: x-spreadsheet library failed to load. Check internet connection.</p>';
return;
}
try {
const spreadsheet = x_spreadsheet('#xspreadsheet');
spreadsheet.loadData(sheetData);
} catch (e) {
console.error('Error:', e);
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: ' + e.message + '</p>';
}
});
</script>
</body>
</html>
BIN
View File
Binary file not shown.
Binary file not shown.
+91
View File
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import os
import sys
import json
from typing import List
from alibabacloud_ocr_api20210707.client import Client as ocr_api20210707Client
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_darabonba_stream.client import Client as StreamClient
from alibabacloud_ocr_api20210707 import models as ocr_api_20210707_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models
class Sample:
def __init__(self):
pass
@staticmethod
def create_client() -> ocr_api20210707Client:
"""
使用凭据初始化账号Client
@return: Client
@throws Exception
"""
# 工程代码建议使用更安全的无AK方式,凭据配置方式请参见:https://help.aliyun.com/document_detail/378659.html。
credentialsConfig = CredentialConfig(
type='access_key',
# 必填参数,此处以从环境变量中获取AccessKey ID为例
access_key_id='LTAI5t6GQdkoqgAEMkMbrCUM',
# 必填参数,此处以从环境变量中获取AccessKey Secret为例
access_key_secret='YIbvdZi0Ne8WYSZ1Qlm805gKVujWEO'
)
credentialsClient = CredentialClient(credentialsConfig)
config = open_api_models.Config(
credential=credentialsClient
)
# Endpoint 请参考 https://api.aliyun.com/product/ocr-api
config.endpoint = f'ocr-api.cn-hangzhou.aliyuncs.com'
return ocr_api20210707Client(config)
@staticmethod
def main(
args: List[str],
) -> None:
client = Sample.create_client()
# 需要安装额外的依赖库,直接点击下载完整工程即可看到所有依赖。
body_stream = StreamClient.read_from_file_path('test.png')
recognize_table_ocr_request = ocr_api_20210707_models.RecognizeTableOcrRequest(
body=body_stream
)
runtime = util_models.RuntimeOptions()
try:
resp = client.recognize_table_ocr_with_options(recognize_table_ocr_request, runtime)
print(json.dumps(resp, default=str, indent=2))
except Exception as error:
# 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
# 错误 message
print(error)
# 诊断地址
#print(error.data.get("Recommend"))
pass
@staticmethod
async def main_async(
args: List[str],
) -> None:
client = Sample.create_client()
# 需要安装额外的依赖库,直接点击下载完整工程即可看到所有依赖。
body_stream = StreamClient.read_from_file_path('<your-file-path>')
recognize_table_ocr_request = ocr_api_20210707_models.RecognizeTableOcrRequest(
body=body_stream
)
runtime = util_models.RuntimeOptions()
try:
resp = await client.recognize_table_ocr_with_options_async(recognize_table_ocr_request, runtime)
print(json.dumps(resp, default=str, indent=2))
except Exception as error:
# 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
# 错误 message
print(error.message)
# 诊断地址
print(error.data.get("Recommend"))
if __name__ == '__main__':
Sample.main(sys.argv[1:])
+101
View File
@@ -0,0 +1,101 @@
import json
import os
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter, column_index_from_string
def xlsx_to_spreadsheet_data(xlsx_path):
wb = load_workbook(xlsx_path, data_only=True)
ws = wb.active
rows = {}
max_row = ws.max_row or 0
max_col = ws.max_column or 0
for r in range(1, max_row + 1):
row_key = r - 1
cells = {}
for c in range(1, max_col + 1):
cell = ws.cell(row=r, column=c)
if cell.value is not None:
val = cell.value
if not isinstance(val, str):
val = str(val)
cells[str(c - 1)] = {"text": val}
if cells:
rows[str(row_key)] = {"cells": cells}
rows["len"] = max_row
merges = []
for merged_range in ws.merged_cells.ranges:
min_row, min_col, max_row2, max_col2 = (
merged_range.min_row,
merged_range.min_col,
merged_range.max_row,
merged_range.max_col,
)
ri = min_row - 1
ci = min_col - 1
rs = max_row2 - min_row
cs = max_col2 - min_col
range_str = f"{get_column_letter(min_col)}{min_row}:{get_column_letter(max_col2)}{max_row2}"
merges.append(range_str)
row_key = str(ri)
if row_key not in rows:
rows[row_key] = {"cells": {}}
cell_key = str(ci)
if cell_key not in rows[row_key]["cells"]:
rows[row_key]["cells"][cell_key] = {}
rows[row_key]["cells"][cell_key]["merge"] = [rs, cs]
sheet_name = ws.title if ws.title else "Sheet1"
cols = {}
for col_letter, dim in ws.column_dimensions.items():
if dim.width:
ci = column_index_from_string(col_letter) - 1
px = max(60, int(dim.width * 8))
cols[str(ci)] = {"width": px}
result = {
"name": sheet_name,
"rows": rows,
"merges": merges,
}
if cols:
result["cols"] = cols
return result
def generate_sheet(xlsx_path, output_html_path=None, template_path=None):
if template_path is None:
template_path = os.path.join(os.path.dirname(__file__), "sheet.html")
data = xlsx_to_spreadsheet_data(xlsx_path)
data_json = json.dumps(data, ensure_ascii=False, indent=2)
data_json = data_json.replace("</script>", "<\\/script>")
with open(template_path, "r", encoding="utf-8") as f:
html = f.read()
html = html.replace("{{DATA}}", data_json)
if output_html_path is None:
output_html_path = xlsx_path.rsplit(".", 1)[0] + ".html"
with open(output_html_path, "w", encoding="utf-8") as f:
f.write(html)
print(f"HTML saved to: {output_html_path}")
return output_html_path
if __name__ == "__main__":
import sys
src = sys.argv[1] if len(sys.argv) > 1 else "111.xlsx"
generate_sheet(src)
+16
View File
@@ -0,0 +1,16 @@
import sys
sys.stdout.reconfigure(encoding='utf-8')
import json
d = json.load(open(r"C:\Users\Idiot\Desktop\temp\sample.json", "r", encoding="utf-8"))
print("Top keys:", list(d.keys()))
print("Data type:", type(d.get("Data")))
data_val = d.get("Data")
if isinstance(data_val, str):
print("Data is a string, trying to parse...")
parsed = json.loads(data_val)
print("Parsed Data keys:", list(parsed.keys()))
elif isinstance(data_val, dict):
print("Data keys:", list(data_val.keys()))
print("prism_tablesInfo exists:", "prism_tablesInfo" in data_val)
+99
View File
@@ -0,0 +1,99 @@
import json
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
def json_to_excel(json_file_path, output_excel_path=None):
with open(json_file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
if output_excel_path is None:
output_excel_path = json_file_path.rsplit('.', 1)[0] + '.xlsx'
wb = Workbook()
thin_border = Border(
left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin')
)
data_field = data.get('Data', {})
if isinstance(data_field, str):
data_field = json.loads(data_field)
tables_info = data_field.get('prism_tablesInfo', [])
for idx, table in enumerate(tables_info):
if idx == 0:
ws = wb.active
ws.title = f"Table_{table.get('tableId', idx)}"
else:
ws = wb.create_sheet(title=f"Table_{table.get('tableId', idx)}")
x_cell_size = table.get('xCellSize', 0)
y_cell_size = table.get('yCellSize', 0)
cell_infos = table.get('cellInfos', [])
grid = {}
for cell in cell_infos:
xsc = cell.get('xsc', 0)
ysc = cell.get('ysc', 0)
xec = cell.get('xec', xsc)
yec = cell.get('yec', ysc)
word = str(cell.get('word', ''))
key = (ysc, xsc)
grid[key] = {
'word': word,
'xsc': xsc,
'xec': xec,
'ysc': ysc,
'yec': yec,
}
for cell_info in cell_infos:
xsc = cell_info.get('xsc', 0)
ysc = cell_info.get('ysc', 0)
xec = cell_info.get('xec', xsc)
yec = cell_info.get('yec', ysc)
word = str(cell_info.get('word', ''))
row_start = ysc + 1
col_start = xsc + 1
row_end = yec + 1
col_end = xec + 1
ws.cell(row=row_start, column=col_start, value=word)
if xec > xsc or yec > ysc:
ws.merge_cells(
start_row=row_start,
start_column=col_start,
end_row=row_end,
end_column=col_end,
)
for r in range(row_start, row_end + 1):
for c in range(col_start, col_end + 1):
cell_obj = ws.cell(row=r, column=c)
cell_obj.border = thin_border
cell_obj.alignment = Alignment(
horizontal='center',
vertical='center',
wrap_text=True,
)
cell_obj.font = Font(name='Arial', size=10)
from openpyxl.utils import get_column_letter
for c in range(1, x_cell_size + 1):
ws.column_dimensions[get_column_letter(c)].width = 15
wb.save(output_excel_path)
return output_excel_path
if __name__ == '__main__':
json_path = 'sample.json'
out_path = '111.xlsx'
result = json_to_excel(json_path, out_path)
print(f"Excel saved to: {result}")
+4
View File
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>x-data-spreadsheet</title>
<style>
body { margin:0; padding:20px; font-family:Arial,sans-serif; background-color:#f5f5f5; }
#xspreadsheet { width:100%; height:600px; box-shadow:0 2px 10px rgba(0,0,0,0.1); background-color:white; }
</style>
<link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css">
</head>
<body>
<h1>x-data-spreadsheet</h1>
<div id="xspreadsheet"></div>
<script src="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.js"></script>
<script>
const sheetData = {{DATA}};
document.addEventListener('DOMContentLoaded', function () {
if (typeof x_spreadsheet === 'undefined') {
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: x-spreadsheet library failed to load. Check internet connection.</p>';
return;
}
try {
const spreadsheet = x_spreadsheet('#xspreadsheet');
spreadsheet.loadData(sheetData);
} catch (e) {
console.error('Error:', e);
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: ' + e.message + '</p>';
}
});
</script>
</body>
</html>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB