From 7ceb03ef8a76efe1b8e2e4de714ef933d139c698 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 20 Mar 2023 14:57:15 +0100 Subject: [PATCH] (bug) unable to export to excel --- CHANGELOG.md | 2 ++ app/models/statistic_type.rb | 10 +++++-- app/services/excel_service.rb | 30 +++++++++++++++++++ .../exports/availabilities_index.xlsx.axlsx | 8 ++--- .../exports/statistics_current.xlsx.axlsx | 6 ++-- .../exports/statistics_global.xlsx.axlsx | 4 +-- app/views/exports/users_members.xlsx.axlsx | 2 +- .../exports/users_reservations.xlsx.axlsx | 2 +- .../exports/users_subscriptions.xlsx.axlsx | 2 +- 9 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 app/services/excel_service.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1a63ee7..a693da787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog Fab-manager +- Fix a bug: in some cases, unable to export to excel files + ## v5.9.0 2023 March 20 - Ability to restrict machine reservations per plan diff --git a/app/models/statistic_type.rb b/app/models/statistic_type.rb index 58a016ae8..d0b44526d 100644 --- a/app/models/statistic_type.rb +++ b/app/models/statistic_type.rb @@ -1,6 +1,10 @@ +# frozen_string_literal: true + +# Allows splinting a StatisticIndex into multiple types. +# e.g. The StatisticIndex "subscriptions" may have types like "1 month", "1 year", etc. class StatisticType < ApplicationRecord - has_one :statistic_index - has_many :statistic_type_sub_types + belongs_to :statistic_index + has_many :statistic_type_sub_types, dependent: :destroy has_many :statistic_sub_types, through: :statistic_type_sub_types - has_many :statistic_custom_aggregations + has_many :statistic_custom_aggregations, dependent: :destroy end diff --git a/app/services/excel_service.rb b/app/services/excel_service.rb new file mode 100644 index 000000000..cfdd97a25 --- /dev/null +++ b/app/services/excel_service.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# Provides methods around Excel files specification +class ExcelService + class << self + # remove all unauthorized characters from the given Excel's worksheet name + # @param name [String] + # @param replace [String] + # @return [String] + def name_safe(name, replace = '-') + name.gsub(%r{[*|\\:"<>?/]}, replace).truncate(31) + end + + # Generate a name for the current type, compatible with Excel worksheet names + # @param type [StatisticType] + # @param workbook [Axlsx::Workbook] + # @return [String] + def statistic_type_sheet_name(type, workbook) + # see https://msdn.microsoft.com/fr-fr/library/c6bdca6y(v=vs.90).aspx for unauthorized character list + name = "#{type.statistic_index.label} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '') + # sheet name is limited to 31 characters + name = if name.length > 31 + "#{type.statistic_index.label.truncate(4, omission: '.')} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '').truncate(31) + end + # we cannot have two sheets with the same name + name = name[0..30] + String((rand * 10).to_i) until workbook.sheet_by_name(name).nil? + name + end + end +end diff --git a/app/views/exports/availabilities_index.xlsx.axlsx b/app/views/exports/availabilities_index.xlsx.axlsx index 58748e4c4..7952956df 100644 --- a/app/views/exports/availabilities_index.xlsx.axlsx +++ b/app/views/exports/availabilities_index.xlsx.axlsx @@ -6,7 +6,7 @@ header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub(' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format ## Machines slots -wb.add_worksheet(name: t('export_availabilities.machines')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.machines'))) do |sheet| ## data table # heading labels @@ -45,7 +45,7 @@ end ## Trainings availabilities -wb.add_worksheet(name: t('export_availabilities.trainings')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.trainings'))) do |sheet| ## data table # heading labels @@ -73,7 +73,7 @@ end ## Spaces slots if Setting.get('spaces_module') - wb.add_worksheet(name: t('export_availabilities.spaces')) do |sheet| + wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.spaces'))) do |sheet| ## data table # heading labels @@ -109,7 +109,7 @@ end ## Events availabilities -wb.add_worksheet(name: t('export_availabilities.events')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.events'))) do |sheet| ## data table # heading labels diff --git a/app/views/exports/statistics_current.xlsx.axlsx b/app/views/exports/statistics_current.xlsx.axlsx index e4b8062c4..f009cab19 100644 --- a/app/views/exports/statistics_current.xlsx.axlsx +++ b/app/views/exports/statistics_current.xlsx.axlsx @@ -6,12 +6,10 @@ bold = wb.styles.add_style b: true 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 -wb.add_worksheet(name: @index.label) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(@index.label)) do |sheet| ## heading stats for the current page sheet.add_row [t('export.entries'), @results['hits']['total']], style: [bold, nil], types: %i[string integer] - if @index.ca - sheet.add_row [t('export.revenue'), @results['aggregations']['total_ca']['value']], style: [bold, nil], types: %i[string float] - end + sheet.add_row [t('export.revenue'), @results['aggregations']['total_ca']['value']], style: [bold, nil], types: %i[string float] if @index.ca sheet.add_row [t('export.average_age'), @results['aggregations']['average_age']['value']], style: [bold, nil], types: %i[string float] unless @type.simple sheet.add_row ["#{t('export.total')} #{@type.label}", @results['aggregations']['total_stat']['value']], diff --git a/app/views/exports/statistics_global.xlsx.axlsx b/app/views/exports/statistics_global.xlsx.axlsx index 2b9a723d5..b2ffc108c 100644 --- a/app/views/exports/statistics_global.xlsx.axlsx +++ b/app/views/exports/statistics_global.xlsx.axlsx @@ -9,9 +9,7 @@ date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_for next unless 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(%r{[*|\\:"<>?/]}, '').truncate(31) - wb.add_worksheet(name: sheet_name) do |sheet| + wb.add_worksheet(name: ExcelService.statistic_type_sheet_name(type, wb)) 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'), diff --git a/app/views/exports/users_members.xlsx.axlsx b/app/views/exports/users_members.xlsx.axlsx index be786b317..877a8bf0b 100644 --- a/app/views/exports/users_members.xlsx.axlsx +++ b/app/views/exports/users_members.xlsx.axlsx @@ -5,7 +5,7 @@ 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 -wb.add_worksheet(name: t('export_members.members')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_members.members'))) do |sheet| ## data table # heading labels columns = [t('export_members.id'), diff --git a/app/views/exports/users_reservations.xlsx.axlsx b/app/views/exports/users_reservations.xlsx.axlsx index 6322d5194..ca2a11b07 100644 --- a/app/views/exports/users_reservations.xlsx.axlsx +++ b/app/views/exports/users_reservations.xlsx.axlsx @@ -5,7 +5,7 @@ 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 -wb.add_worksheet(name: t('export_reservations.reservations')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_reservations.reservations'))) do |sheet| ## data table # heading labels diff --git a/app/views/exports/users_subscriptions.xlsx.axlsx b/app/views/exports/users_subscriptions.xlsx.axlsx index 05af09724..b8e43ac26 100644 --- a/app/views/exports/users_subscriptions.xlsx.axlsx +++ b/app/views/exports/users_subscriptions.xlsx.axlsx @@ -5,7 +5,7 @@ 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 -wb.add_worksheet(name: t('export_subscriptions.subscriptions')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_subscriptions.subscriptions'))) do |sheet| ## data table # heading labels