create_excel_tables.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import pandas as pd
  2. import numpy as np
  3. import xlsxwriter
  4. import openpyxl
  5. from openpyxl.worksheet.datavalidation import DataValidation
  6. # Values have to be a list of list
  7. # Title_string have to be a list of list of strings
  8. class CreateTable:
  9. def __init__(self, dict_, insert=True, path=None, index=None, axis=0, ordered_by=[], order=[]):
  10. self.insert = insert
  11. self.path = path
  12. self.index = index
  13. self.dict = dict_
  14. self.axis = axis
  15. self.ordered_by = ordered_by
  16. self.order = order
  17. self.column = []
  18. self.currency_format = []
  19. for key, v in self.dict.items():
  20. self.column += [key]
  21. if self.order:
  22. ordered_column = []
  23. for each_key in self.order:
  24. if each_key in self.column:
  25. ordered_column += [each_key]
  26. self.column.remove(each_key)
  27. else:
  28. assert (False, 'Order contains values which are not in the Table')
  29. self.column = ordered_column + self.column
  30. self.dataframes = pd.DataFrame(dict([(k, pd.Series(v)) for k, v in self.dict.items()]), columns=self.column)
  31. def create_writer(self):
  32. return pd.ExcelWriter(self.path, engine='xlsxwriter') # openpyxl xlsxwriter
  33. def create_openpyxl_writer(self):
  34. return pd.ExcelWriter(self.path, engine='openpyxl') # openpyxl xlsxwriter
  35. def load_openpyxl_workbook(self, additional_path=''):
  36. if additional_path:
  37. return openpyxl.load_workbook("dropdown.xlsx")
  38. return openpyxl.load_workbook("dropdown.xlsx")
  39. def create_workbook(self):
  40. return xlsxwriter.Workbook(self.path)
  41. def create_openpyxl_workbook(self):
  42. return openpyxl.Workbook(self.path)
  43. def get_dataframe(self):
  44. return self.dataframes
  45. def append_to_csv(self):
  46. self.dataframes.to_csv(path_or_buf=self.path, index=self.index, mode='a')
  47. def add_style_(self, style_dict):
  48. return self.dataframes.style.format(style_dict)
  49. def set_style_properties(self, style_dict):
  50. return self.dataframes.style.set_properties(**style_dict)
  51. def create_format(self):
  52. self.currency_format = self.create_workbook().add_format()
  53. def export_to_csv(self):
  54. if self.order:
  55. raise NotImplementedError
  56. if self.ordered_by == []:
  57. self.dataframes.to_csv(path_or_buf=self.path, index=self.index)
  58. else:
  59. self.dataframes = self.dataframes.sort_values(by=self.ordered_by, axis=self.axis)
  60. self.dataframes.to_csv(path_or_buf=self.path, index=self.index)
  61. def export_to_excel(self, writer, additional_dataframes=[]):
  62. if self.ordered_by == []:
  63. pass
  64. else:
  65. self.dataframes = self.dataframes.sort_values(by=self.ordered_by, axis=self.axis)
  66. # Format
  67. if self.currency_format:
  68. self.currency_format.set_align('center')
  69. else:
  70. self.create_format()
  71. self.currency_format.set_align('center')
  72. # First Tab
  73. self.dataframes.to_excel(excel_writer=writer, sheet_name='Karte ' + str(1), index=False)
  74. for column in self.dataframes:
  75. column_width = max(self.dataframes[column].astype(str).map(len).max(), len(column) + 5)
  76. col_idx = self.dataframes.columns.get_loc(column)
  77. writer.sheets['Karte ' + str(1)].set_column(col_idx, col_idx, column_width, cell_format=self.currency_format)
  78. # All other Tabs
  79. for count, each_dataframe in enumerate(additional_dataframes):
  80. each_dataframe.to_excel(writer, sheet_name='Karte ' + str(count + 2), index=False)
  81. for column in each_dataframe:
  82. column_width = max(each_dataframe[column].astype(str).map(len).max(), len(column) + 5)
  83. col_idx = each_dataframe.columns.get_loc(column)
  84. writer.sheets['Karte ' + str(count + 2)].set_column(col_idx, col_idx, column_width, cell_format=self.currency_format)
  85. writer.save()
  86. def append_df_to_xlsx(self, df): # TODO extract even more
  87. df_excel = pd.read_excel(self.path)
  88. self.dataframes = pd.concat([df_excel, df], ignore_index=True)
  89. self.export_to_excel(self.create_writer())
  90. def create_custom_excel_economy_calendar(self, writer):
  91. if self.ordered_by == []:
  92. pass
  93. else:
  94. self.dataframes = self.dataframes.sort_values(by=self.ordered_by, axis=self.axis)
  95. # Format
  96. self.currency_format = self.create_workbook().add_format()
  97. self.currency_format.set_align('center')
  98. self.currency_format.set_align('center')
  99. self.dataframes.to_excel(excel_writer=writer, sheet_name='Karte ' + str(1), index=False)
  100. for column in self.dataframes:
  101. column_width = max(self.dataframes[column].astype(str).map(len).max(), len(column) + 5)
  102. col_idx = self.dataframes.columns.get_loc(column)
  103. writer.sheets['Karte ' + str(1)].set_column(col_idx, col_idx, column_width, cell_format=self.currency_format)
  104. writer.save()
  105. def add_another_page_to_excel(self, additional_dataframes, writer):
  106. # Format
  107. currency_format = self.create_workbook().add_format()
  108. currency_format.set_align('center')
  109. currency_format.set_align('center')
  110. for count, each_dataframe in enumerate(additional_dataframes):
  111. each_dataframe.to_excel(writer, sheet_name='Karte ' + str(count + 2), index=False)
  112. for column in each_dataframe:
  113. column_width = max(each_dataframe[column].astype(str).map(len).max(), len(column) + 5)
  114. col_idx = each_dataframe.columns.get_loc(column)
  115. writer.sheets['Karte ' + str(count + 2)].set_column(col_idx, col_idx, column_width, cell_format=currency_format)
  116. return writer
  117. def create_hyperlink_from_string(self, name: str):
  118. self.dataframes.style.format({name: make_clickable})
  119. def make_clickable(val):
  120. # target _blank to open new window
  121. return '<a target="_blank" href="{}">{}</a>'.format(val, val)
  122. class XlsxWriterClass:
  123. def __init__(self, path, another_sheet=''):
  124. '''
  125. :param path: Absolute Path
  126. :param list_of_sheets: in this version only two sheets can be created. A little bit sloppy..
  127. '''
  128. self.path = path
  129. self.wb = xlsxwriter.Workbook(self.path)
  130. self.ws = self.wb.add_worksheet('Karte 1')
  131. self.last_column = 0
  132. self.alphabet = ['A', 'B', 'C', 'D', 'E',
  133. 'F', 'G', 'H', 'I', 'J',
  134. 'K', 'L', 'M', 'N', 'O',
  135. 'P', 'Q', 'R', 'S', 'T',
  136. 'U', 'V', 'W', 'X', 'Y',
  137. 'Z',
  138. 'AA', 'AB', 'AC', 'AD', 'AE',
  139. 'AF', 'AG', 'AH', 'AI', 'AJ',
  140. 'AK', 'AL', 'AM', 'AN', 'AO',
  141. 'AP', 'AQ', 'AR', 'AS', 'AT',
  142. 'AU', 'AV', 'AW', 'AX', 'AY',
  143. 'AZ', ]
  144. if another_sheet:
  145. self.another_sheet = self.wb.add_worksheet('Karte2')
  146. self.last_column_sheet2 = 1
  147. def create_format_for_data(self, added_style):
  148. self.style_ = self.wb.add_format(added_style)
  149. def del_current_format_for_data(self):
  150. self.style_ = False
  151. def set_column_prop(self, col, width):
  152. self.ws.set_column(first_col=col, last_col=col, width=width)
  153. def set_row(self, count_rows, height):
  154. for row in range(1, count_rows):
  155. self.ws.set_row(row, height=height)
  156. def write_data_in_free_column_with_bold_header(self, data, column_range=1, format_=False, data_with_own_format={}):
  157. '''
  158. :param data: dict format [key: list_of_values] or list of lists
  159. :param column_range: only for list of lists
  160. :param data_with_own_format: tuple of data and format : (data, format)
  161. :return:
  162. '''
  163. assert column_range + self.last_column <= len(self.alphabet), 'Alphabet len is to small add new Columns [self.alphabet]'
  164. if data_with_own_format:
  165. special_data = data_with_own_format[0]
  166. special_data_format = data_with_own_format[1]
  167. if isinstance(data, dict):
  168. for col, key in enumerate(data.keys()):
  169. offset=0
  170. # Header
  171. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1), key, self.wb.add_format({'bold': True}))
  172. if data_with_own_format:
  173. for row in range(1, 1 + len(special_data[key])):
  174. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), special_data[key][row - 1],
  175. self.wb.add_format(special_data_format))
  176. offset += 1
  177. for row in range(1, 1 + len(data[key])):
  178. if format_:
  179. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row+offset), data[key][row - 1], self.style_)
  180. else:
  181. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row+offset), data[key][row - 1])
  182. self.last_column += len(data.keys())
  183. else:
  184. for col in range(0, column_range):
  185. offset=0
  186. # Header
  187. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1), data[col][0], {'bold': True})
  188. if data_with_own_format:
  189. for row in range(1, 1 + len(special_data[col])):
  190. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), special_data[col][row],
  191. self.wb.add_format(special_data_format))
  192. offset += 1
  193. for row in range(1, 1 + len(data[col])):
  194. if format_:
  195. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row+offset), data[col][row], self.style_)
  196. else:
  197. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row+offset), data[col][row])
  198. self.last_column += len(data)
  199. def write_dict_of_dicts_in_free_column_with_color_for_each_cell(self, data, column_range=1):
  200. '''
  201. :param data: dict format [key: {Color: [...], Value : [...]}]
  202. :param column_range: len of used columns for dict only in assertions
  203. :return:
  204. '''
  205. assert column_range + self.last_column <= len(self.alphabet), 'Alphabet len is to small add new Columns [self.alphabet]'
  206. for col, key in enumerate(data.keys()):
  207. # Header
  208. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1), key, self.wb.add_format({'bold': True}))
  209. for row in range(1, 1 + len(data[key])):
  210. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), data[key][row - 1]['Value'],
  211. self.wb.add_format({'font_color': data[key][row - 1]['Color']}))
  212. self.last_column += len(data.keys())
  213. def write_data_in_free_column_with_custom_style_and_dropdown(self, data, column_range=1, format_=False, source=[1]):
  214. '''
  215. :param data: dict format [key: list_of_values] or list of lists
  216. :param column_range: only for list of lists
  217. :param source : list of dropdown values
  218. :return:
  219. '''
  220. assert column_range + self.last_column <= len(self.alphabet), 'Alphabet len is to small add new Columns [self.alphabet]'
  221. if isinstance(data, dict):
  222. for col, key in enumerate(data.keys()):
  223. # Header
  224. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1), key, self.wb.add_format({'bold': True}))
  225. for row in range(1, 1 + len(data[key])):
  226. if format_:
  227. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), data[key][row - 1], self.style_)
  228. self.ws.conditional_format('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'type': 'cell',
  229. 'criteria': '>=',
  230. 'value': 10,
  231. 'format': self.wb.add_format(
  232. {
  233. 'bg_color': '#90ee90',
  234. 'font_color': 'black'})})
  235. self.ws.data_validation('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'validate': 'list',
  236. 'source': source
  237. })
  238. else:
  239. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), data[key][row - 1])
  240. self.ws.conditional_format('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'type': 'cell',
  241. 'criteria': '>=',
  242. 'value': 10,
  243. 'format': self.wb.add_format(
  244. {
  245. 'bg_color': '#90ee90',
  246. 'font_color': 'black'})})
  247. self.ws.data_validation('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'validate': 'list',
  248. 'source': source
  249. })
  250. self.last_column += len(data.keys())
  251. else:
  252. for col in range(0, column_range):
  253. # Header
  254. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1), data[col][0], {'bold': True})
  255. for row in range(1, 1 + len(data[col])):
  256. if format_:
  257. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), data[col][row], self.style_)
  258. self.ws.conditional_format('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'type': 'cell',
  259. 'criteria': '>=',
  260. 'value': 10,
  261. 'format': self.wb.add_format(
  262. {
  263. 'bg_color': '#90ee90',
  264. 'font_color': 'black'})})
  265. self.ws.data_validation('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'validate': 'list',
  266. 'source': source
  267. })
  268. else:
  269. self.ws.write('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), data[col][row])
  270. self.ws.conditional_format('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'type': 'cell',
  271. 'criteria': '>=',
  272. 'value': 10,
  273. 'format': self.wb.add_format(
  274. {
  275. 'bg_color': '#90ee90',
  276. 'font_color': 'black'})})
  277. self.ws.data_validation('{}{}'.format(self.alphabet[col + self.last_column], 1 + row), {'validate': 'list',
  278. 'source': source
  279. })
  280. self.last_column += len(data)
  281. def write_data_in_free_column_on_another_sheet(self, data, column_range=1, format_=False):
  282. '''
  283. TODO This function does not work properly, generalization is recommended
  284. :param data: dict format or list of lists
  285. :param column_range:
  286. :return:
  287. '''
  288. assert column_range <= len(self.alphabet), 'Alphabet len is to small add new Columns [self.alphabet]'
  289. if isinstance(data, dict):
  290. pass
  291. else:
  292. for col in range(0, column_range): # Generates 99 "ip" address in the Column A;
  293. for row in range(self.last_column_sheet2, self.last_column_sheet2 + len(data[col])):
  294. if format_:
  295. self.another_sheet.write('{}{}'.format(self.alphabet[col], row), data[col][row - 1], self.style_)
  296. else:
  297. self.another_sheet.write('{}{}'.format(self.alphabet[col], row), data[col][row - 1])
  298. self.last_column_sheet2 = len(data)
  299. def save_and_close_excel(self):
  300. self.wb.close()