convert_xlsx.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import inspect
  2. import os
  3. import sys
  4. sys.path.append(os.path.dirname(__file__) + "/../")
  5. from format_convert.convert_tree import _Document, _Page, _Table
  6. import logging
  7. import traceback
  8. import pandas
  9. import numpy as np
  10. import xlrd
  11. from format_convert.utils import get_logger, log, memory_decorator
  12. from format_convert.wrapt_timeout_decorator import timeout
  13. @memory_decorator
  14. def xlsx2text(path, unique_type_dir):
  15. log("into xlsx2text")
  16. try:
  17. try:
  18. # sheet_name=None, 即拿取所有sheet,存为dict
  19. df_dict = pandas.read_excel(path, header=None, keep_default_na=False, sheet_name=None)
  20. except Exception as e:
  21. log("xlsx format error!")
  22. return [-3]
  23. df_list = [sheet for sheet in df_dict.values()]
  24. sheet_text = ""
  25. for df in df_list:
  26. text = '<table border="1">' + "\n"
  27. for index, row in df.iterrows():
  28. text = text + "<tr>"
  29. for r in row:
  30. text = text + "<td>" + str(r) + "</td>" + "\n"
  31. # print(text)
  32. text = text + "</tr>" + "\n"
  33. text = text + "</table>" + "\n"
  34. sheet_text += text
  35. return [sheet_text]
  36. except Exception as e:
  37. log("xlsx2text error!")
  38. traceback.print_exc()
  39. return [-1]
  40. class XlsxConvert:
  41. def __init__(self, path, unique_type_dir):
  42. self._doc = _Document(path)
  43. self.path = path
  44. self.unique_type_dir = unique_type_dir
  45. @timeout(30, timeout_exception=TimeoutError, use_signals=False)
  46. def read(self):
  47. # pandas
  48. df = pandas.read_excel(self.path, header=None, keep_default_na=False, sheet_name=None)
  49. # xlrd 为了读取合并单元格
  50. workbook = xlrd.open_workbook(self.path)
  51. return df, workbook
  52. def init_package(self):
  53. # 各个包初始化
  54. try:
  55. self.df, self.workbook = self.read()
  56. self.sheet_list = [sheet for sheet in self.df.values()]
  57. # 防止读太多空列空行
  58. self.col_limit = 100
  59. self.row_limit = 2000
  60. self.re_read = 0
  61. for s in self.sheet_list:
  62. if s.shape[1] > self.col_limit and s.shape[0] > self.row_limit:
  63. self.re_read = 3
  64. break
  65. elif s.shape[0] > self.row_limit:
  66. self.re_read = 2
  67. break
  68. elif s.shape[1] > self.col_limit:
  69. self.re_read = 1
  70. break
  71. if self.re_read == 3:
  72. self.df = pandas.read_excel(self.path, header=None, keep_default_na=False,
  73. sheet_name=None, usecols=[x for x in range(self.col_limit)],
  74. nrows=self.row_limit)
  75. if self.re_read == 2:
  76. self.df = pandas.read_excel(self.path, header=None, keep_default_na=False,
  77. sheet_name=None, nrows=self.row_limit)
  78. elif self.re_read == 1:
  79. self.df = pandas.read_excel(self.path, header=None, keep_default_na=False,
  80. sheet_name=None, usecols=[x for x in range(self.col_limit)])
  81. if self.re_read > 0:
  82. self.sheet_list = [sheet for sheet in self.df.values()]
  83. # print(self.sheet_list[0].shape)
  84. except:
  85. log("cannot open xlsx!")
  86. traceback.print_exc()
  87. self._doc.error_code = [-3]
  88. def convert(self):
  89. self.init_package()
  90. if self._doc.error_code is not None:
  91. return
  92. sheet_no = 0
  93. for sheet in self.sheet_list:
  94. # 删除xlsx全为空的行列
  95. sheet.dropna(how='all', axis=1, inplace=True)
  96. sheet.dropna(how='all', axis=0, inplace=True)
  97. self._page = _Page(None, sheet_no)
  98. self.convert_page(sheet, sheet_no)
  99. if self._doc.error_code is None and self._page.error_code is not None:
  100. self._doc.error_code = self._page.error_code
  101. self._doc.add_child(self._page)
  102. sheet_no += 1
  103. def convert_page2(self, sheet):
  104. text = '<table border="1">' + "\n"
  105. # 剔除多余空列
  106. max_row_len = 0
  107. max_col_len = 0
  108. if self.re_read:
  109. for index, row in sheet.iterrows():
  110. col_len = 0
  111. row_empty_flag = 1
  112. for i in range(len(row)):
  113. if row[i] not in [None, "", np.nan]:
  114. row_empty_flag = 0
  115. col_len = i
  116. if self.re_read == 3 or self.re_read == 1:
  117. if col_len > max_col_len:
  118. max_col_len = col_len
  119. if self.re_read == 3 or self.re_read == 2:
  120. if row_empty_flag == 0:
  121. max_row_len = index
  122. for index, row in sheet.iterrows():
  123. if self.re_read == 3 or self.re_read == 2:
  124. if index > max_row_len:
  125. break
  126. text = text + "<tr>"
  127. if self.re_read == 3 or self.re_read == 1:
  128. row = row[:max_col_len+1]
  129. for r in row:
  130. text = text + "<td>" + str(r) + "</td>" + "\n"
  131. # print(text)
  132. text = text + "</tr>" + "\n"
  133. text = text + "</table>" + "\n"
  134. _table = _Table(text, (0, 0, 0, 0), is_html=True)
  135. self._page.add_child(_table)
  136. def convert_page(self, sheet, sheet_no):
  137. # 剔除多余空列
  138. max_row_len = 0
  139. max_col_len = 0
  140. if self.re_read:
  141. for index, row in sheet.iterrows():
  142. col_len = 0
  143. row_empty_flag = 1
  144. for i in range(len(row)):
  145. if row[i] not in [None, "", np.nan]:
  146. row_empty_flag = 0
  147. col_len = i
  148. if self.re_read == 3 or self.re_read == 1:
  149. if col_len > max_col_len:
  150. max_col_len = col_len
  151. if self.re_read == 3 or self.re_read == 2:
  152. if row_empty_flag == 0:
  153. max_row_len = index
  154. row_list = []
  155. for index, row in sheet.iterrows():
  156. if self.re_read == 3 or self.re_read == 2:
  157. if index > max_row_len:
  158. break
  159. if self.re_read == 3 or self.re_read == 1:
  160. row = row[:max_col_len+1]
  161. col_list = []
  162. for r in row:
  163. col_list.append(str(r))
  164. row_list.append(col_list)
  165. # xlrd 获取合并单元格位置
  166. sheet_xlrd = self.workbook.sheet_by_index(sheet_no)
  167. merged_cell_list = sheet_xlrd.merged_cells
  168. merged_cell_list.sort(key=lambda x: (x[0], x[1], x[2], x[3]))
  169. # print("merged_cell_list", merged_cell_list)
  170. # 复制填充合并单元格
  171. for row_start, row_end, col_start, col_end in merged_cell_list:
  172. if row_start >= len(row_list) or row_end > len(row_list):
  173. continue
  174. if col_start >= len(row_list[row_start]) or col_end > len(row_list[row_start]):
  175. continue
  176. copy_cell = row_list[row_start][col_start]
  177. for i in range(row_start, row_end):
  178. row = row_list[i]
  179. # 第一行补少一个,其他行需补多一个
  180. if i == row_start:
  181. col_start_real = col_start+1
  182. else:
  183. col_start_real = col_start
  184. for j in range(col_start_real, col_end):
  185. if row[j] == "":
  186. row[j] = copy_cell
  187. # 拼接html表格
  188. text = '<table border="1">' + "\n"
  189. for row in row_list:
  190. text = text + "<tr>"
  191. for col in row:
  192. text = text + "<td>" + str(col) + "</td>" + "\n"
  193. text = text + "</tr>" + "\n"
  194. text = text + "</table>" + "\n"
  195. _table = _Table(text, (0, 0, 0, 0), is_html=True)
  196. self._page.add_child(_table)
  197. def get_html(self):
  198. try:
  199. self.convert()
  200. except:
  201. traceback.print_exc()
  202. self._doc.error_code = [-1]
  203. if self._doc.error_code is not None:
  204. return self._doc.error_code
  205. return self._doc.get_html()