wb = xlsx_package.workbook

header = wb.styles.add_style :b => true, :bg_color => Stylesheet.primary.upcase.gsub('#', 'FF'), :fg_color => 'FFFFFFFF'
date = wb.styles.add_style :format_code => Rails.application.secrets.excel_date_format

@indices.each do |index|
  if index.table
    index.statistic_types.each do |type|
      # see https://msdn.microsoft.com/fr-fr/library/c6bdca6y(v=vs.90).aspx for unauthorized character list
      sheet_name = "#{index.label} - #{type.label}".gsub(/[*|\\:"<>?\/]/,'').truncate(31)
      wb.add_worksheet(name: sheet_name) do |sheet|

        ## data table
        # heading labels
        columns = [t('export.date'), t('export.user'), t('export.email'), t('export.phone'), t('export.gender'), t('export.age'), t('export.type')]
        columns.push type.label unless type.simple
        index.statistic_fields.each do |f|
          columns.push f.label
        end
        columns.push t('export.revenue') if index.ca
        sheet.add_row columns, :style => header

        # data rows
        @results['hits']['hits'].each do |hit|
          # check that the current result is for the given index and type
          if hit['_type'] == index.es_type_key and hit['_source']['type'] == type.key
            # get matching objects
            user = get_item(@users, hit['_source']['userId'])
            subtype = get_item(type.statistic_sub_types, hit['_source']['subType'], 'key')
            # start to fill data and associated styles and data-types
            data = [
                Date::strptime(hit['_source']['date'],'%Y-%m-%d'),
                (user ? user.profile.full_name : "ID #{hit['_source']['userId']}"),
                (user ? user.email : ''),
                (user ? user.profile.phone : ''),
                t("export.#{hit['_source']['gender']}"),
                hit['_source']['age'],
                subtype.nil? ? "" : subtype.label
            ]
            styles = [date, nil, nil, nil, nil, nil, nil]
            types = [:date, :string, :string, :string, :string, :integer, :string]
            # do not proceed with the 'stat' field if the type is declared as 'simple'
            unless type.simple
              data.push hit['_source']['stat']
              styles.push nil
              types.push :string
            end
            # proceed additional fields
            index.statistic_fields.each do |f|
              field_data = hit['_source'][f.key]
              case f.data_type
                when 'date'
                  data.push Date::strptime(field_data, '%Y-%m-%d')
                  styles.push date
                  types.push :date
                when 'list'
                  data.push field_data.map{|e| e['name'] }.join(', ')
                  styles.push nil
                  types.push :string
                when 'number'
                  data.push field_data
                  styles.push nil
                  types.push :float
                else
                  data.push field_data
                  styles.push nil
                  types.push :string
              end

            end
            # proceed the 'ca' field if requested
            if index.ca
              data.push hit['_source']['ca']
              styles.push nil
              types.push :float
            end
            # finally, add the data row to the workbook's sheet
            sheet.add_row data, :style =>  styles, :types => types
          end
        end
      end
    end
  end
end