excel_sheet.rb 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. class ExcelSheet
  2. def initialize(title:, header:, records:, timezone: nil, locale:)
  3. @title = title
  4. @header = header
  5. @records = records
  6. @timezone = timezone.presence || Setting.get('timezone_default')
  7. @locale = locale || Locale.default
  8. @tempfile = Tempfile.new('excel-export.xls')
  9. @workbook = WriteExcel.new(@tempfile)
  10. @worksheet = @workbook.add_worksheet
  11. @contents = nil
  12. @current_row = 0
  13. @current_column = 0
  14. @lookup_cache = {}
  15. @format_time = @workbook.add_format(num_format: 'yyyy-mm-dd hh:mm:ss')
  16. @format_date = @workbook.add_format(num_format: 'yyyy-mm-dd')
  17. @format_headline = @workbook.add_format
  18. @format_headline.set_bold
  19. @format_headline.set_size(14)
  20. @format_headline.set_color('black')
  21. @format_header = @workbook.add_format
  22. @format_header.set_italic
  23. @format_header.set_bg_color('gray')
  24. @format_header.set_color('white')
  25. @format_footer = @workbook.add_format
  26. @format_footer.set_italic
  27. @format_footer.set_color('gray')
  28. @format_footer.set_size(8)
  29. end
  30. def contents
  31. file = File.new(@tempfile, 'r')
  32. contents = file.read
  33. file.close
  34. contents
  35. end
  36. def content
  37. gen_header
  38. gen_rows
  39. gen_footer
  40. contents
  41. end
  42. def gen_header
  43. @worksheet.write_string(@current_row, @current_column, @title, @format_headline)
  44. @worksheet.set_row(0, 18)
  45. @current_row += 2
  46. @current_column = 0
  47. @header.each do |header|
  48. if header[:width]
  49. @worksheet.set_column(@current_column, @current_column, header[:width])
  50. end
  51. @worksheet.write_string(@current_row, @current_column, header[:display] || header[:name], @format_header)
  52. @current_column += 1
  53. end
  54. end
  55. def gen_rows
  56. @records.each do |record|
  57. gen_row_by_array(record)
  58. end
  59. end
  60. def gen_row_by_array(record)
  61. @current_row += 1
  62. @current_column = 0
  63. record.each do |item|
  64. begin
  65. if item.acts_like?(:time)
  66. value_convert(item, nil, { data_type: 'datetime' })
  67. elsif item.acts_like?(:date)
  68. value_convert(item, nil, { data_type: 'datetime' })
  69. elsif item.is_a?(Integer) || item.is_a?(Float)
  70. value_convert(item, nil, { data_type: 'integer' })
  71. else
  72. value_convert(item, nil, { data_type: 'string' })
  73. end
  74. rescue => e
  75. Rails.logger.error e
  76. end
  77. @current_column += 1
  78. end
  79. end
  80. def gen_row_by_header(record, additional = {})
  81. @current_row += 1
  82. @current_column = 0
  83. @header.each do |header|
  84. begin
  85. value_convert(record, header[:name], header, additional)
  86. rescue => e
  87. Rails.logger.error e
  88. end
  89. @current_column += 1
  90. end
  91. end
  92. def gen_footer
  93. @current_row += 2
  94. @worksheet.write_string(@current_row, 0, "#{Translation.translate(@locale, 'Timezone')}: #{@timezone}", @format_footer)
  95. @workbook.close
  96. end
  97. def timestamp_in_localtime(time)
  98. return if time.blank?
  99. time.in_time_zone(@timezone).strftime('%F %T') # "2019-08-19 16:21:52"
  100. end
  101. def value_lookup(record, attribute, additional)
  102. value = record[attribute.to_sym]
  103. if attribute[-3, 3] == '_id'
  104. ref = attribute[0, attribute.length - 3]
  105. if record.respond_to?(ref.to_sym)
  106. @lookup_cache[attribute] ||= {}
  107. return @lookup_cache[attribute][value] if @lookup_cache[attribute][value]
  108. ref_object = record.send(ref.to_sym)
  109. ref_name = value
  110. if ref_object.respond_to?(:fullname)
  111. ref_name = ref_object.fullname
  112. elsif ref_object.respond_to?(:name)
  113. ref_name = ref_object.name
  114. end
  115. @lookup_cache[attribute][value] = ref_name
  116. return ref_name
  117. end
  118. end
  119. value = record.try(attribute)
  120. # if no value exists, check additional values
  121. if !value && additional && additional[attribute.to_sym]
  122. value = additional[attribute.to_sym]
  123. end
  124. if value.is_a?(Array)
  125. value = value.join(',')
  126. end
  127. value
  128. end
  129. def value_convert(record, attribute, object, additional = {})
  130. value = if attribute
  131. value_lookup(record, attribute, additional)
  132. else
  133. record
  134. end
  135. case object[:data_type]
  136. when 'boolean', 'select'
  137. if object[:data_option] && object[:data_option]['options'] && object[:data_option]['options'][value]
  138. value = object[:data_option]['options'][value]
  139. end
  140. @worksheet.write_string(@current_row, @current_column, value) if value.present?
  141. when 'datetime'
  142. @worksheet.write_date_time(@current_row, @current_column, timestamp_in_localtime(value), @format_time) if value.present?
  143. when 'date'
  144. @worksheet.write_date_time(@current_row, @current_column, value.to_s, @format_date) if value.present?
  145. when 'integer'
  146. @worksheet.write_number(@current_row, @current_column, value) if value.present?
  147. else
  148. @worksheet.write_string(@current_row, @current_column, value.to_s) if value.present?
  149. end
  150. end
  151. end