gomyck-tools 1.3.1__py3-none-any.whl → 1.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ctools/__init__.py +0 -0
- ctools/aes_tools.py +35 -0
- ctools/api_result.py +55 -0
- ctools/application.py +386 -0
- ctools/b64.py +7 -0
- ctools/bashPath.py +13 -0
- ctools/bottle_web_base.py +169 -0
- ctools/bottle_webserver.py +143 -0
- ctools/bottle_websocket.py +75 -0
- ctools/browser_element_tools.py +314 -0
- ctools/call.py +71 -0
- ctools/cftp.py +74 -0
- ctools/cjson.py +54 -0
- ctools/ckafka.py +159 -0
- ctools/compile_tools.py +18 -0
- ctools/console.py +55 -0
- ctools/coord_trans.py +127 -0
- ctools/credis.py +111 -0
- ctools/cron_lite.py +252 -0
- ctools/ctoken.py +34 -0
- ctools/cword.py +30 -0
- ctools/czip.py +130 -0
- ctools/database.py +185 -0
- ctools/date_utils.py +43 -0
- ctools/dict_wrapper.py +20 -0
- ctools/douglas_rarefy.py +136 -0
- ctools/download_tools.py +57 -0
- ctools/enums.py +4 -0
- ctools/ex.py +31 -0
- ctools/excelOpt.py +36 -0
- ctools/html_soup.py +35 -0
- ctools/http_utils.py +24 -0
- ctools/images_tools.py +27 -0
- ctools/imgDialog.py +44 -0
- ctools/metrics.py +131 -0
- ctools/mqtt_utils.py +289 -0
- ctools/obj.py +20 -0
- ctools/pacth.py +74 -0
- ctools/plan_area_tools.py +97 -0
- ctools/process_pool.py +36 -0
- ctools/pty_tools.py +72 -0
- ctools/resource_bundle_tools.py +121 -0
- ctools/rsa.py +70 -0
- ctools/screenshot_tools.py +127 -0
- ctools/sign.py +20 -0
- ctools/sm_tools.py +49 -0
- ctools/snow_id.py +76 -0
- ctools/str_diff.py +20 -0
- ctools/string_tools.py +85 -0
- ctools/sys_info.py +157 -0
- ctools/sys_log.py +89 -0
- ctools/thread_pool.py +35 -0
- ctools/upload_tools.py +40 -0
- ctools/win_canvas.py +83 -0
- ctools/win_control.py +106 -0
- ctools/word_fill.py +562 -0
- ctools/word_fill_entity.py +46 -0
- ctools/work_path.py +69 -0
- {gomyck_tools-1.3.1.dist-info → gomyck_tools-1.3.2.dist-info}/METADATA +1 -1
- gomyck_tools-1.3.2.dist-info/RECORD +62 -0
- gomyck_tools-1.3.2.dist-info/top_level.txt +1 -0
- gomyck_tools-1.3.1.dist-info/RECORD +0 -4
- gomyck_tools-1.3.1.dist-info/top_level.txt +0 -1
- {gomyck_tools-1.3.1.dist-info → gomyck_tools-1.3.2.dist-info}/WHEEL +0 -0
ctools/word_fill.py
ADDED
@@ -0,0 +1,562 @@
|
|
1
|
+
import os
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
import xlrd
|
5
|
+
import xlwt
|
6
|
+
from docx import Document
|
7
|
+
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
|
8
|
+
from docx.oxml import OxmlElement, parse_xml
|
9
|
+
from docx.oxml.ns import qn, nsdecls
|
10
|
+
from docx.shared import Pt, RGBColor
|
11
|
+
from docxtpl import DocxTemplate, RichText
|
12
|
+
from openpyxl import load_workbook
|
13
|
+
from openpyxl.styles import Side, Border
|
14
|
+
from xlstpl import writer as xls_writer
|
15
|
+
from xlsxtpl import writerx as xlsx_writerx
|
16
|
+
from xlutils.copy import copy
|
17
|
+
|
18
|
+
from ctools import cjson
|
19
|
+
from ctools.word_fill_entity import WordTable, WordCell, Style, Font, Alignment
|
20
|
+
|
21
|
+
EXCEL_WORD_ALIGNMENT = {"left": WD_TABLE_ALIGNMENT.LEFT,
|
22
|
+
"center": WD_TABLE_ALIGNMENT.CENTER,
|
23
|
+
"right": WD_TABLE_ALIGNMENT.RIGHT}
|
24
|
+
EXCEL_WORD_VERTICAL = {"top": WD_ALIGN_VERTICAL.TOP,
|
25
|
+
"center": WD_ALIGN_VERTICAL.CENTER,
|
26
|
+
"bottom": WD_ALIGN_VERTICAL.BOTTOM}
|
27
|
+
|
28
|
+
|
29
|
+
class DocxTools:
|
30
|
+
|
31
|
+
@staticmethod
|
32
|
+
def get_docx(path=None):
|
33
|
+
return Document(path)
|
34
|
+
|
35
|
+
@staticmethod
|
36
|
+
def add_rich_text(wildcard: dict):
|
37
|
+
try:
|
38
|
+
new_wildcard = {}
|
39
|
+
if wildcard:
|
40
|
+
for k, v in wildcard.items():
|
41
|
+
if "_color" in k:
|
42
|
+
n_k = k[:k.index('_color')]
|
43
|
+
new_wildcard[n_k] = RichText(wildcard[n_k], color=v)
|
44
|
+
elif k not in new_wildcard:
|
45
|
+
new_wildcard[k] = v
|
46
|
+
return new_wildcard
|
47
|
+
except Exception as e:
|
48
|
+
print("使用word_fill.add_rich_text函数异常: %s" % e)
|
49
|
+
return wildcard
|
50
|
+
|
51
|
+
def tables_format(self, input_path: str, table_data: List[dict] = None):
|
52
|
+
if table_data:
|
53
|
+
doc = Document(input_path)
|
54
|
+
for index, table in enumerate(doc.tables):
|
55
|
+
if index <= len(table_data) - 1:
|
56
|
+
td = table_data[index]
|
57
|
+
start_position = td.get('start_position')
|
58
|
+
data = td.get('data')
|
59
|
+
|
60
|
+
for r in range(0, len(data)):
|
61
|
+
for c in range(0, len(data[r])):
|
62
|
+
row = r + start_position[0]
|
63
|
+
col = c + start_position[1]
|
64
|
+
|
65
|
+
for i in range((row - len(table.rows)) + 1):
|
66
|
+
table.add_row()
|
67
|
+
try:
|
68
|
+
table.cell(row, col).text = str(data[r][c])
|
69
|
+
except IndexError:
|
70
|
+
pass
|
71
|
+
|
72
|
+
self.set_cell_border(table)
|
73
|
+
doc.save(input_path)
|
74
|
+
|
75
|
+
def set_cell_border(self, table):
|
76
|
+
return self.set_table_boarder(
|
77
|
+
table,
|
78
|
+
top={"sz": 4, "val": "single", "color": "#000000"},
|
79
|
+
bottom={"sz": 4, "val": "single", "color": "#000000"},
|
80
|
+
left={"sz": 4, "val": "single", "color": "#000000"},
|
81
|
+
right={"sz": 4, "val": "single", "color": "#000000"},
|
82
|
+
insideV={"sz": 4, "val": "single", "color": "#000000"},
|
83
|
+
insideH={"sz": 4, "val": "single", "color": "#000000"}
|
84
|
+
)
|
85
|
+
|
86
|
+
@staticmethod
|
87
|
+
def set_table_boarder(table, **kwargs):
|
88
|
+
"""
|
89
|
+
Set table`s border
|
90
|
+
Usage:
|
91
|
+
set_table_border(
|
92
|
+
cell,
|
93
|
+
top={"sz": 12, "val": "single", "color": "#FF0000"},
|
94
|
+
bottom={"sz": 12, "color": "#00FF00", "val": "single"},
|
95
|
+
left={"sz": 24, "val": "dashed"},
|
96
|
+
right={"sz": 12, "val": "dashed"},
|
97
|
+
)
|
98
|
+
"""
|
99
|
+
borders = OxmlElement('w:tblBorders')
|
100
|
+
for tag in ('bottom', 'top', 'left', 'right', 'insideV', 'insideH'):
|
101
|
+
edge_data = kwargs.get(tag)
|
102
|
+
if edge_data:
|
103
|
+
any_border = OxmlElement(f'w:{tag}')
|
104
|
+
for key in ["sz", "val", "color", "space", "shadow"]:
|
105
|
+
if key in edge_data:
|
106
|
+
any_border.set(qn(f'w:{key}'), str(edge_data[key]))
|
107
|
+
borders.append(any_border)
|
108
|
+
table._tbl.tblPr.append(borders)
|
109
|
+
|
110
|
+
@staticmethod
|
111
|
+
def merge_word(document: Document, input_file):
|
112
|
+
"""
|
113
|
+
合并docx文件内容
|
114
|
+
:param document:
|
115
|
+
:param input_file:
|
116
|
+
:return:
|
117
|
+
"""
|
118
|
+
doc = Document(input_file)
|
119
|
+
for element in doc.element.body:
|
120
|
+
document.element.body.append(element)
|
121
|
+
|
122
|
+
@staticmethod
|
123
|
+
def merge_excel(document: Document, excel_path):
|
124
|
+
"""
|
125
|
+
合并excel文件内容
|
126
|
+
:param document:
|
127
|
+
:param excel_path: excel文件路径
|
128
|
+
:return:
|
129
|
+
"""
|
130
|
+
wt = ExcelTools().get_excel_cells(excel_path)
|
131
|
+
max_rows = wt.max_rows
|
132
|
+
max_cols = wt.max_cols
|
133
|
+
cells = wt.cells
|
134
|
+
merged_cells = wt.merged_cells
|
135
|
+
|
136
|
+
doc_body = document.element.body
|
137
|
+
# 创建Word表格
|
138
|
+
table = document.add_table(rows=max_rows, cols=max_cols, style="Table Grid")
|
139
|
+
if len(doc_body) > 0:
|
140
|
+
doc_body[-1].addnext(table._tbl)
|
141
|
+
table.autofit = False
|
142
|
+
|
143
|
+
for cell in cells:
|
144
|
+
position = cell.position
|
145
|
+
value = cell.value
|
146
|
+
style = cell.style
|
147
|
+
|
148
|
+
t_cell = table.cell(position[0], position[1])
|
149
|
+
t_cell.text = str(value)
|
150
|
+
paragraph = t_cell.paragraphs[0]
|
151
|
+
run = paragraph.runs[0]
|
152
|
+
|
153
|
+
if style:
|
154
|
+
if style.font:
|
155
|
+
run.font.name = style.font.name
|
156
|
+
run.font.size = Pt(style.font.size)
|
157
|
+
run.font.bold = style.font.bold
|
158
|
+
run.font.italic = style.font.italic
|
159
|
+
run.font.underline = style.font.underline
|
160
|
+
run._element.rPr.rFonts.set(qn('w:eastAsia'), style.font.name)
|
161
|
+
if style.font.color:
|
162
|
+
run.font.color.rgb = RGBColor.from_string(style.font.color)
|
163
|
+
|
164
|
+
if style.bg_color:
|
165
|
+
t_cell._tc.get_or_add_tcPr().append(parse_xml(r'<w:shd {} w:fill="{bgColor}"/>'.format(nsdecls('w'), bgColor=style.bg_color)))
|
166
|
+
|
167
|
+
paragraph.paragraph_format.alignment = EXCEL_WORD_ALIGNMENT.get(style.alignment.horizontal)
|
168
|
+
t_cell.vertical_alignment = EXCEL_WORD_VERTICAL.get(style.alignment.vertical)
|
169
|
+
|
170
|
+
# 合并单元格
|
171
|
+
for mc in merged_cells:
|
172
|
+
first_cell = None
|
173
|
+
first_group_cell = []
|
174
|
+
for p in mc:
|
175
|
+
for i, r in enumerate(p):
|
176
|
+
if i == 0:
|
177
|
+
first_cell = table.cell(r[0], r[1])
|
178
|
+
first_group_cell.append(first_cell)
|
179
|
+
else:
|
180
|
+
first_cell.merge(table.cell(r[0], r[1]))
|
181
|
+
|
182
|
+
if len(first_group_cell) > 1:
|
183
|
+
for i, cell in enumerate(first_group_cell):
|
184
|
+
if i == 0:
|
185
|
+
first_cell = cell
|
186
|
+
else:
|
187
|
+
first_cell.merge(cell)
|
188
|
+
|
189
|
+
|
190
|
+
class ExcelTools:
|
191
|
+
|
192
|
+
@staticmethod
|
193
|
+
def tables_format_xls(input_path: str, table_data: List[dict] = None):
|
194
|
+
if table_data:
|
195
|
+
wb = xlrd.open_workbook(input_path, formatting_info=True)
|
196
|
+
wb = copy(wb)
|
197
|
+
|
198
|
+
borders = xlwt.Borders()
|
199
|
+
borders.left = 1
|
200
|
+
borders.right = 1
|
201
|
+
borders.top = 1
|
202
|
+
borders.bottom = 1
|
203
|
+
|
204
|
+
style = xlwt.XFStyle()
|
205
|
+
style.borders = borders
|
206
|
+
|
207
|
+
sheet = wb.get_sheet(0)
|
208
|
+
for td in table_data:
|
209
|
+
start_position = td.get('start_position')
|
210
|
+
data = td.get('data')
|
211
|
+
|
212
|
+
for r in range(0, len(data)):
|
213
|
+
for c in range(0, len(data[r])):
|
214
|
+
row = r + start_position[0]
|
215
|
+
col = c + start_position[1]
|
216
|
+
sheet.write(row, col, data[r][c], style=style)
|
217
|
+
|
218
|
+
wb.save(input_path)
|
219
|
+
|
220
|
+
@staticmethod
|
221
|
+
def tables_format_xlsx(input_path: str, table_data: List[dict] = None):
|
222
|
+
if table_data:
|
223
|
+
wb = load_workbook(input_path)
|
224
|
+
sheet = wb[wb.sheetnames[0]]
|
225
|
+
|
226
|
+
side = Side(style='thin', color='FF000000')
|
227
|
+
border = Border(left=side, right=side, top=side, bottom=side)
|
228
|
+
|
229
|
+
for td in table_data:
|
230
|
+
start_position = td.get('start_position')
|
231
|
+
data = td.get('data')
|
232
|
+
|
233
|
+
for r in range(0, len(data)):
|
234
|
+
for c in range(0, len(data[r])):
|
235
|
+
row = r + start_position[0] + 1
|
236
|
+
col = c + start_position[1] + 1
|
237
|
+
cell = sheet.cell(row=row, column=col)
|
238
|
+
cell.value = data[r][c]
|
239
|
+
cell.border = border
|
240
|
+
|
241
|
+
wb.save(filename=input_path)
|
242
|
+
|
243
|
+
def get_excel_cells(self, excel_path) -> WordTable:
|
244
|
+
"""
|
245
|
+
获取excel所有有效单元格信息
|
246
|
+
:param excel_path:
|
247
|
+
:return:
|
248
|
+
"""
|
249
|
+
cells = []
|
250
|
+
merged_cells = []
|
251
|
+
eff_max_rows, eff_max_cols, real_max_rows, real_max_cols = 0, 0, 0, 0
|
252
|
+
suffix = os.path.splitext(excel_path)[-1].lower()
|
253
|
+
if suffix == ".xls":
|
254
|
+
wb = xlrd.open_workbook(excel_path, formatting_info=True)
|
255
|
+
sheet = wb.sheets()[0]
|
256
|
+
|
257
|
+
eff_max_rows, eff_min_rows, eff_max_cols, eff_min_cols, real_max_rows, real_max_cols = self.get_excel_rows_cols(sheet, is_xlsx=False)
|
258
|
+
|
259
|
+
for r in range(0, real_max_rows):
|
260
|
+
for c in range(0, real_max_cols):
|
261
|
+
val = sheet.cell_value(r, c)
|
262
|
+
if val and len(str(val).strip()) > 0:
|
263
|
+
position = [r - eff_min_rows, c - eff_min_cols]
|
264
|
+
xfx = sheet.cell_xf_index(position[0], position[1])
|
265
|
+
xf = wb.xf_list[xfx]
|
266
|
+
|
267
|
+
horizontal = None
|
268
|
+
vertical = None
|
269
|
+
hor_align = xf.alignment.hor_align
|
270
|
+
if hor_align == 1:
|
271
|
+
horizontal = "left"
|
272
|
+
elif hor_align == 2:
|
273
|
+
horizontal = "center"
|
274
|
+
elif hor_align == 3:
|
275
|
+
horizontal = "right"
|
276
|
+
|
277
|
+
vert_align = xf.alignment.vert_align
|
278
|
+
if vert_align == 0:
|
279
|
+
vertical = "top"
|
280
|
+
elif vert_align == 1:
|
281
|
+
vertical = "center"
|
282
|
+
elif vert_align == 2:
|
283
|
+
vertical = "bottom"
|
284
|
+
|
285
|
+
font = wb.font_list[xf.font_index]
|
286
|
+
|
287
|
+
style = Style()
|
288
|
+
font_size = round(font.height / 20)
|
289
|
+
if font_size:
|
290
|
+
if eff_max_cols < 20:
|
291
|
+
font_size = 5 if round(font_size * 0.8) <= 5 else round(font_size * 0.8)
|
292
|
+
else:
|
293
|
+
font_size = 5 if round(font_size * 0.7) <= 5 else round(font_size * 0.7)
|
294
|
+
style.font = Font(font.name, font_size, bool(font.bold), bool(font.italic), bool(font.underlined))
|
295
|
+
# style.font.set_color(cell.font.color)
|
296
|
+
style.alignment = Alignment(horizontal, vertical)
|
297
|
+
# style.set_bg_color(cell.fill.start_color)
|
298
|
+
|
299
|
+
word_cell = WordCell()
|
300
|
+
word_cell.position = position
|
301
|
+
word_cell.value = str(val)
|
302
|
+
word_cell.style = style
|
303
|
+
cells.append(word_cell)
|
304
|
+
|
305
|
+
merged_cells = self.get_excel_merged_cells(sheet, eff_min_rows, eff_min_cols, is_xlsx=False)
|
306
|
+
|
307
|
+
elif suffix == ".xlsx":
|
308
|
+
wb = load_workbook(excel_path)
|
309
|
+
sheet = wb[wb.sheetnames[0]]
|
310
|
+
eff_max_rows, eff_min_rows, eff_max_cols, eff_min_cols, real_max_rows, real_max_cols = self.get_excel_rows_cols(sheet)
|
311
|
+
|
312
|
+
for r in range(1, real_max_rows + 1):
|
313
|
+
for c in range(1, real_max_cols + 1):
|
314
|
+
cell = sheet.cell(r, c)
|
315
|
+
val = cell.value
|
316
|
+
if val and len(str(val).strip()) > 0:
|
317
|
+
position = [r - eff_min_rows, c - eff_min_cols]
|
318
|
+
|
319
|
+
style = Style()
|
320
|
+
font_size = cell.font.size
|
321
|
+
if font_size:
|
322
|
+
if eff_max_cols < 20:
|
323
|
+
font_size = 5 if round(font_size * 0.8) <= 5 else round(font_size * 0.8)
|
324
|
+
else:
|
325
|
+
font_size = 5 if round(font_size * 0.7) <= 5 else round(font_size * 0.7)
|
326
|
+
|
327
|
+
style.font = Font(cell.font.name, font_size, cell.font.bold, cell.font.italic, cell.font.underline)
|
328
|
+
style.font.set_color(cell.font.color)
|
329
|
+
vertical = cell.alignment.vertical
|
330
|
+
if cell.alignment.vertical is None:
|
331
|
+
vertical = "bottom"
|
332
|
+
style.alignment = Alignment(cell.alignment.horizontal, vertical)
|
333
|
+
style.set_bg_color(cell.fill.start_color)
|
334
|
+
|
335
|
+
word_cell = WordCell()
|
336
|
+
word_cell.position = position
|
337
|
+
word_cell.value = str(val)
|
338
|
+
word_cell.style = style
|
339
|
+
cells.append(word_cell)
|
340
|
+
|
341
|
+
merged_cells = self.get_excel_merged_cells(sheet, eff_min_rows, eff_min_cols)
|
342
|
+
|
343
|
+
word_table = WordTable()
|
344
|
+
word_table.max_rows = eff_max_rows
|
345
|
+
word_table.max_cols = eff_max_cols
|
346
|
+
word_table.cells = cells
|
347
|
+
word_table.merged_cells = merged_cells
|
348
|
+
return word_table
|
349
|
+
|
350
|
+
@staticmethod
|
351
|
+
def get_excel_rows_cols(sheet, is_xlsx=True):
|
352
|
+
"""
|
353
|
+
获取excel有效的最大行数和列数
|
354
|
+
:param sheet:
|
355
|
+
:param is_xlsx:
|
356
|
+
:return:
|
357
|
+
"""
|
358
|
+
row_list, col_list = [], []
|
359
|
+
if is_xlsx:
|
360
|
+
start_index = 1
|
361
|
+
real_max_rows, real_max_cols = sheet.max_row, sheet.max_column
|
362
|
+
real_max_cols = sheet.max_column
|
363
|
+
else:
|
364
|
+
start_index = 0
|
365
|
+
real_max_rows, real_max_cols = sheet.nrows, sheet.ncols
|
366
|
+
|
367
|
+
index = 0
|
368
|
+
eff_max_rows, eff_max_cols = real_max_rows, real_max_cols
|
369
|
+
eff_min_rows, eff_min_cols = start_index, start_index
|
370
|
+
for r in range(start_index, real_max_rows):
|
371
|
+
for c in range(start_index, real_max_cols):
|
372
|
+
val = sheet.cell(r, c).value if is_xlsx else sheet.cell_value(r, c)
|
373
|
+
if val and len(str(val).strip()) > 0:
|
374
|
+
row_list.append(r)
|
375
|
+
col_list.append(c)
|
376
|
+
if index == 0:
|
377
|
+
eff_min_rows = r
|
378
|
+
eff_min_cols = c
|
379
|
+
index = 1
|
380
|
+
if len(row_list) > 0:
|
381
|
+
eff_max_rows = max(row_list) - min(row_list) + start_index + 1
|
382
|
+
if len(col_list) > 0:
|
383
|
+
eff_max_cols = max(col_list) - min(col_list) + start_index + 1
|
384
|
+
return eff_max_rows, eff_min_rows, eff_max_cols, eff_min_cols, real_max_rows, real_max_cols
|
385
|
+
|
386
|
+
@staticmethod
|
387
|
+
def get_excel_merged_cells(sheet, d_row, d_col, is_xlsx=True):
|
388
|
+
"""
|
389
|
+
获取excel所有合并的单元格信息
|
390
|
+
:param sheet:
|
391
|
+
:param d_row: 有效起始行和实际起始行的差值
|
392
|
+
:param d_col:
|
393
|
+
:param is_xlsx:
|
394
|
+
:return:
|
395
|
+
"""
|
396
|
+
merged_cells = []
|
397
|
+
if is_xlsx:
|
398
|
+
merged_ranges = sheet.merged_cells.ranges
|
399
|
+
for merged_range in merged_ranges:
|
400
|
+
cells = []
|
401
|
+
for r in range(merged_range.min_row, merged_range.max_row + 1):
|
402
|
+
rows = []
|
403
|
+
for c in range(merged_range.min_col, merged_range.max_col + 1):
|
404
|
+
rows.append([r - d_row, c - d_col])
|
405
|
+
cells.append(rows)
|
406
|
+
merged_cells.append(cells)
|
407
|
+
else:
|
408
|
+
mergeds = sheet.merged_cells
|
409
|
+
for merged in mergeds:
|
410
|
+
cells = []
|
411
|
+
for r in range(merged[0], merged[1]):
|
412
|
+
rows = []
|
413
|
+
for c in range(merged[2], merged[3]):
|
414
|
+
rows.append([r - d_row, c - d_col])
|
415
|
+
cells.append(rows)
|
416
|
+
merged_cells.append(cells)
|
417
|
+
|
418
|
+
return merged_cells
|
419
|
+
|
420
|
+
|
421
|
+
def template_format(input_path: str, output_path: str, wildcard: dict = None, table_data=None):
|
422
|
+
"""
|
423
|
+
填充模板信息
|
424
|
+
:param input_path: 模板文件路径
|
425
|
+
:param output_path: 填充后输出文件路径
|
426
|
+
:param wildcard: 模板通配符数据
|
427
|
+
:param table_data: 模板中表格数据
|
428
|
+
:return:
|
429
|
+
"""
|
430
|
+
if os.path.exists(input_path):
|
431
|
+
suffix = os.path.splitext(input_path)[-1].lower()
|
432
|
+
if table_data and not isinstance(table_data, list):
|
433
|
+
table_data = cjson.loads(table_data)
|
434
|
+
|
435
|
+
if suffix == ".xls":
|
436
|
+
tpl = xls_writer.BookWriter(input_path)
|
437
|
+
tpl.render_book([wildcard])
|
438
|
+
tpl.save(output_path)
|
439
|
+
ExcelTools().tables_format_xls(output_path, table_data)
|
440
|
+
elif suffix == ".xlsx":
|
441
|
+
tpl = xlsx_writerx.BookWriter(input_path)
|
442
|
+
tpl.render_book([wildcard])
|
443
|
+
tpl.save(output_path)
|
444
|
+
ExcelTools().tables_format_xlsx(output_path, table_data)
|
445
|
+
elif suffix == ".docx":
|
446
|
+
tpl = DocxTemplate(input_path)
|
447
|
+
wildcard = DocxTools.add_rich_text(wildcard)
|
448
|
+
tpl.render(wildcard)
|
449
|
+
tpl.save(output_path)
|
450
|
+
DocxTools().tables_format(output_path, table_data)
|
451
|
+
|
452
|
+
|
453
|
+
def check_format(input_path: str):
|
454
|
+
"""
|
455
|
+
校验文件后缀与文件格式是否匹配
|
456
|
+
:param input_path:
|
457
|
+
:return:
|
458
|
+
"""
|
459
|
+
res = True
|
460
|
+
try:
|
461
|
+
suffix = os.path.splitext(input_path)[-1].lower()
|
462
|
+
if suffix == ".xls":
|
463
|
+
xls_writer.BookWriter(input_path)
|
464
|
+
elif suffix == ".xlsx":
|
465
|
+
xlsx_writerx.BookWriter(input_path)
|
466
|
+
elif suffix == ".docx":
|
467
|
+
DocxTemplate(input_path)
|
468
|
+
except Exception:
|
469
|
+
res = False
|
470
|
+
return res
|
471
|
+
|
472
|
+
def excel_optimize(input_path: str):
|
473
|
+
"""
|
474
|
+
优化excel内容清除无法使用的隐患
|
475
|
+
:param input_path:
|
476
|
+
:return:
|
477
|
+
"""
|
478
|
+
try:
|
479
|
+
suffix = os.path.splitext(input_path)[-1].lower()
|
480
|
+
if suffix == ".xlsx":
|
481
|
+
wb = load_workbook(input_path)
|
482
|
+
sheet = wb[wb.sheetnames[0]]
|
483
|
+
real_max_rows, real_max_cols = sheet.max_row, sheet.max_column
|
484
|
+
is_optimize = False
|
485
|
+
|
486
|
+
if real_max_cols >= 100:
|
487
|
+
sheet.delete_cols(100, real_max_cols)
|
488
|
+
is_optimize = True
|
489
|
+
|
490
|
+
if is_optimize:
|
491
|
+
wb.save(input_path)
|
492
|
+
except Exception as e:
|
493
|
+
print("优化模板内容清除无法使用的隐患异常: %s" % e)
|
494
|
+
|
495
|
+
|
496
|
+
# 示例用法:从第1行到第5行、从第1列到第3列的区域复制到Word文档中
|
497
|
+
# excel_file = r'C:\Users\DELL\xxx/xxx-rpa/document\test-2024-04-01_09-05-26.xlsx' # Excel文件名
|
498
|
+
# excel_file_1 = r'E:\test\c.xlsx' # Excel文件名
|
499
|
+
# excel_file_2 = r'E:\test\b.xlsx' # Excel文件名
|
500
|
+
# word_file = r'E:\test\test.docx' # 输出Word文件名
|
501
|
+
# # xls_insert_docx(excel_file, word_file, start_row=1, end_row=11, start_col=1, end_col=28)
|
502
|
+
#
|
503
|
+
# doc = Document()
|
504
|
+
# input_files = r"E:\test\样式问题2_11-31-28.docx"
|
505
|
+
# DocxTools.merge_word(doc, input_files)
|
506
|
+
# DocxTools.merge_excel(doc, excel_file_1)
|
507
|
+
# DocxTools.merge_word(doc, input_files)
|
508
|
+
# DocxTools.merge_excel(doc, excel_file_1)
|
509
|
+
# DocxTools.merge_excel(doc, excel_file_2)
|
510
|
+
# DocxTools.merge_excel(doc, excel_file_1)
|
511
|
+
# DocxTools.merge_word(doc, input_files)
|
512
|
+
#
|
513
|
+
# doc.save(word_file)
|
514
|
+
|
515
|
+
|
516
|
+
# input_path = [r"E:\test\a.xlsx", r"E:\test\哈尔滨地铁数据文书模板.docx"]
|
517
|
+
#
|
518
|
+
#
|
519
|
+
# wildcard = {"title": "模板标题", "department": "技术平台部"}
|
520
|
+
# table_1 = {
|
521
|
+
# 'start_position': (13, 0),
|
522
|
+
# 'data': [['111', '112', '113'], ['121', '122', '123']]
|
523
|
+
# }
|
524
|
+
#
|
525
|
+
# table_2 = {
|
526
|
+
# 'start_position': (20, 0),
|
527
|
+
# 'data': [['211', '212', '213'], ['221', '222', '223']]
|
528
|
+
# }
|
529
|
+
#
|
530
|
+
# table_3 = {
|
531
|
+
# 'start_position': (1, 0),
|
532
|
+
# 'data': [['311', '312', '313'], ['321', '322', '323']]
|
533
|
+
# }
|
534
|
+
#
|
535
|
+
# table = {
|
536
|
+
# 'start_position': (13, 0),
|
537
|
+
# 'data': [['111', '112', '113'], ['121', '122', '123']]
|
538
|
+
# }
|
539
|
+
# doc_1 = [table]
|
540
|
+
# doc_2 = [table]
|
541
|
+
#
|
542
|
+
# doc_table = [doc_1, doc_2]
|
543
|
+
#
|
544
|
+
#
|
545
|
+
# doc_table_data = cjson.dumps(doc_table)
|
546
|
+
# rest_data = cjson.loads(doc_table_data)
|
547
|
+
#
|
548
|
+
# # print(type(doc_table_data), doc_table_data)
|
549
|
+
#
|
550
|
+
# output_dir = r"E:\test\out"
|
551
|
+
# for i, path in enumerate(input_path):
|
552
|
+
# output_path = os.path.join(output_dir, os.path.split(path)[-1])
|
553
|
+
# template_format(path, output_path, wildcard=wildcard, doc_table_data=rest_data[i])
|
554
|
+
|
555
|
+
|
556
|
+
# ext = os.path.splitext(input_path)[-1]
|
557
|
+
# print(check_format(input_path))
|
558
|
+
|
559
|
+
# from docxtpl import DocxTemplate, RichText
|
560
|
+
|
561
|
+
|
562
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
|
4
|
+
class Alignment:
|
5
|
+
def __init__(self, horizontal=None, vertical=None):
|
6
|
+
self.horizontal = horizontal
|
7
|
+
self.vertical = vertical
|
8
|
+
|
9
|
+
|
10
|
+
class Font:
|
11
|
+
def __init__(self, name=None, size: int = None, bold: bool = False, italic: bool = False, underline=None):
|
12
|
+
self.name = name
|
13
|
+
self.size = size
|
14
|
+
self.color = None
|
15
|
+
self.bold = bold
|
16
|
+
self.italic = italic
|
17
|
+
self.underline = underline
|
18
|
+
|
19
|
+
def set_color(self, color):
|
20
|
+
if color and color.type == 'rgb':
|
21
|
+
self.color = color.rgb[2:]
|
22
|
+
|
23
|
+
|
24
|
+
class Style:
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
self.font = None
|
28
|
+
self.bg_color = None
|
29
|
+
self.alignment: Alignment = Alignment()
|
30
|
+
|
31
|
+
def set_bg_color(self, color):
|
32
|
+
if color.type == 'rgb' and color.rgb != "00000000":
|
33
|
+
self.bg_color = color.rgb[2:]
|
34
|
+
|
35
|
+
|
36
|
+
class WordCell:
|
37
|
+
position: list = []
|
38
|
+
value: str = None
|
39
|
+
style: Style = None
|
40
|
+
|
41
|
+
|
42
|
+
class WordTable:
|
43
|
+
max_rows: int = None
|
44
|
+
max_cols: int = None
|
45
|
+
cells: List[WordCell] = None
|
46
|
+
merged_cells: list = None
|
ctools/work_path.py
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
import inspect
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
|
5
|
+
|
6
|
+
def get_current_path(subPath: str = '') -> str:
|
7
|
+
"""
|
8
|
+
获取当前文件所在路径
|
9
|
+
:param subPath: 子路径
|
10
|
+
:return: 当前文件所在路径
|
11
|
+
"""
|
12
|
+
if getattr(sys, 'frozen', False):
|
13
|
+
base_path = sys._MEIPASS
|
14
|
+
else:
|
15
|
+
caller_frame = inspect.currentframe().f_back
|
16
|
+
caller_path = caller_frame.f_globals["__file__"]
|
17
|
+
base_path = os.path.dirname(caller_path)
|
18
|
+
return os.path.join(base_path, subPath)
|
19
|
+
|
20
|
+
|
21
|
+
def get_app_path(subPath: str = '') -> str:
|
22
|
+
"""
|
23
|
+
获取应用程序工作时所在路径
|
24
|
+
:param subPath: 子路径
|
25
|
+
:return: 应用程序工作时所在路径
|
26
|
+
"""
|
27
|
+
if getattr(sys, 'frozen', False):
|
28
|
+
base_path = sys._MEIPASS
|
29
|
+
else:
|
30
|
+
base_path = os.getcwd()
|
31
|
+
while not os.path.isfile(os.path.join(base_path, 'README.md')):
|
32
|
+
base_path = os.path.dirname(base_path)
|
33
|
+
return os.path.join(base_path, subPath)
|
34
|
+
|
35
|
+
|
36
|
+
def get_user_work_path(subPath: str = '', mkdir: bool = False):
|
37
|
+
"""
|
38
|
+
获取用户工作目录
|
39
|
+
:param subPath: 拼接的子路径
|
40
|
+
:param mkdir: 是否创建目录
|
41
|
+
:return: 用户工作目录
|
42
|
+
"""
|
43
|
+
path = os.path.join(os.path.expanduser("~"), subPath)
|
44
|
+
if mkdir and not os.path.exists(path): os.makedirs(path, exist_ok=True)
|
45
|
+
return path
|
46
|
+
|
47
|
+
|
48
|
+
def get_user_temp_path(subPath: str = '') -> str:
|
49
|
+
"""
|
50
|
+
获取临时文件夹所在路径
|
51
|
+
:return: 临时文件夹所在路径
|
52
|
+
"""
|
53
|
+
return os.path.join(os.environ.get('TEMP'), subPath)
|
54
|
+
|
55
|
+
|
56
|
+
def get_Users_path(subPath: str = '') -> str:
|
57
|
+
"""
|
58
|
+
获取用户目录所在路径 C:/Users
|
59
|
+
:return: 用户目录所在路径
|
60
|
+
"""
|
61
|
+
return os.path.join(os.path.dirname(os.path.expanduser("~")), subPath)
|
62
|
+
|
63
|
+
|
64
|
+
def get_install_path(subPath: str = '') -> str:
|
65
|
+
"""
|
66
|
+
获取安装包安装的路径
|
67
|
+
:return: 安装包安装的路径
|
68
|
+
"""
|
69
|
+
return os.path.join(os.getcwd(), subPath)
|