You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

123 lines
2.8 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. import re
  4. from io import BytesIO
  5. import openpyxl
  6. import xlrd
  7. from openpyxl import load_workbook
  8. from openpyxl.styles import Font
  9. from openpyxl.utils import get_column_letter
  10. import frappe
  11. ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
  12. # return xlsx file object
  13. def make_xlsx(data, sheet_name, wb=None, column_widths=None):
  14. column_widths = column_widths or []
  15. if wb is None:
  16. wb = openpyxl.Workbook(write_only=True)
  17. ws = wb.create_sheet(sheet_name, 0)
  18. for i, column_width in enumerate(column_widths):
  19. if column_width:
  20. ws.column_dimensions[get_column_letter(i + 1)].width = column_width
  21. row1 = ws.row_dimensions[1]
  22. row1.font = Font(name='Calibri', bold=True)
  23. for row in data:
  24. clean_row = []
  25. for item in row:
  26. if isinstance(item, str) and (sheet_name not in ['Data Import Template', 'Data Export']):
  27. value = handle_html(item)
  28. else:
  29. value = item
  30. if isinstance(item, str) and next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
  31. # Remove illegal characters from the string
  32. value = re.sub(ILLEGAL_CHARACTERS_RE, '', value)
  33. clean_row.append(value)
  34. ws.append(clean_row)
  35. xlsx_file = BytesIO()
  36. wb.save(xlsx_file)
  37. return xlsx_file
  38. def handle_html(data):
  39. # return if no html tags found
  40. data = frappe.as_unicode(data)
  41. if '<' not in data:
  42. return data
  43. if '>' not in data:
  44. return data
  45. from html2text import HTML2Text
  46. h = HTML2Text()
  47. h.unicode_snob = True
  48. h = h.unescape(data or "")
  49. obj = HTML2Text()
  50. obj.ignore_links = True
  51. obj.body_width = 0
  52. try:
  53. value = obj.handle(h)
  54. except Exception:
  55. # unable to parse html, send it raw
  56. return data
  57. value = ", ".join(value.split(' \n'))
  58. value = " ".join(value.split('\n'))
  59. value = ", ".join(value.split('# '))
  60. return value
  61. def read_xlsx_file_from_attached_file(file_url=None, fcontent=None, filepath=None):
  62. if file_url:
  63. _file = frappe.get_doc("File", {"file_url": file_url})
  64. filename = _file.get_full_path()
  65. elif fcontent:
  66. filename = BytesIO(fcontent)
  67. elif filepath:
  68. filename = filepath
  69. else:
  70. return
  71. rows = []
  72. wb1 = load_workbook(filename=filename, read_only=True, data_only=True)
  73. ws1 = wb1.active
  74. for row in ws1.iter_rows():
  75. tmp_list = []
  76. for cell in row:
  77. tmp_list.append(cell.value)
  78. rows.append(tmp_list)
  79. return rows
  80. def read_xls_file_from_attached_file(content):
  81. book = xlrd.open_workbook(file_contents=content)
  82. sheets = book.sheets()
  83. sheet = sheets[0]
  84. rows = []
  85. for i in range(sheet.nrows):
  86. rows.append(sheet.row_values(i))
  87. return rows
  88. def build_xlsx_response(data, filename):
  89. xlsx_file = make_xlsx(data, filename)
  90. # write out response as a xlsx type
  91. frappe.response['filename'] = filename + '.xlsx'
  92. frappe.response['filecontent'] = xlsx_file.getvalue()
  93. frappe.response['type'] = 'binary'