From 1a717e507d53bc908482de4f7c50f3b6bf717d11 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 17 Jan 2025 13:46:36 -0500 Subject: [PATCH 1/3] prepend option set name to level --- app/models/forms/export.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/models/forms/export.rb b/app/models/forms/export.rb index 0ba9290c27..494dd86998 100644 --- a/app/models/forms/export.rb +++ b/app/models/forms/export.rb @@ -169,7 +169,9 @@ def to_xls # is the option set multilevel? if os.level_names.present? os.level_names.each_with_index do |level, l_index| - level_name = vanillify(level.values[0]) + # prepend option set name so that level names are unique + # this avoids duplicate header errors + level_name = os_name + "_" + vanillify(level.values[0]) # Append level name to qtype type_to_push = "#{qtype_converted} #{level_name}" @@ -381,7 +383,8 @@ def options_to_xls(option_sets, locales) if node.level.present? # per XLSform style, option sets with levels need to have the # list_name replaced with the level name to distinguish each row. - listname_to_push = node.level_name + # prepend unique identifier to avoid duplicate header errors + listname_to_push = vanillify(os.name) + "_" + node.level_name # Only attempt to access node ancestors if they exist if node.ancestry_depth > 1 @@ -418,7 +421,9 @@ def options_to_xls(option_sets, locales) # omit last entry (lowest level) if os.level_names.present? os.level_names[0..-2].each do |level| - header_row.push(vanillify(level.values[0])) + + # prepend unique identifier + header_row.push(vanillify(os.name) + '_' + vanillify(level.values[0])) # increment column counter column_counter += 1 From 3ea3484ffb015d0f0e70bf783a3ea8e397a79ae8 Mon Sep 17 00:00:00 2001 From: Kevin Cooper Date: Wed, 22 Jan 2025 15:41:34 -0500 Subject: [PATCH 2/3] default allow_choice_duplicates to yes --- app/models/forms/export.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/forms/export.rb b/app/models/forms/export.rb index 494dd86998..5423689e7f 100644 --- a/app/models/forms/export.rb +++ b/app/models/forms/export.rb @@ -76,7 +76,6 @@ def to_xls end questions.row(0).push("name", "required", "relevant", "constraint", "choice_filter") - settings.row(0).push("form_title", "form_id", "version", "default_language") group_depth = 1 # assume base level repeat_depth = 1 @@ -263,13 +262,15 @@ def to_xls end ## Settings + settings.row(0).push("form_title", "form_id", "version", "default_language", "allow_choice_duplicates") + lang = @form.mission.setting.preferred_locales[0].to_s version = if @form.current_version.present? @form.current_version.decorate.name else "1" end - settings.row(1).push(@form.name, @form.id, version, lang) + settings.row(1).push(@form.name, @form.id, version, lang, "yes") ## Write file = StringIO.new From d2e31ce1123722c67eff674ef2d16bc72a257561 Mon Sep 17 00:00:00 2001 From: Kevin Cooper Date: Wed, 22 Jan 2025 15:53:24 -0500 Subject: [PATCH 3/3] factor out unique_level_name method --- app/models/forms/export.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/forms/export.rb b/app/models/forms/export.rb index 5423689e7f..418bee9edb 100644 --- a/app/models/forms/export.rb +++ b/app/models/forms/export.rb @@ -154,10 +154,9 @@ def to_xls # if we have an option set, identify and save it so that we can add it to the choices sheet later. # then, write the question, splitting it into multiple questions if there are option set levels. - os_name = "" choice_filter = "" if q.option_set_id.present? - os = OptionSet.find(q.option_set_id) + os = q.option_set option_sets_used.push(q.option_set_id) # include leading space to respect XLSForm format @@ -168,9 +167,7 @@ def to_xls # is the option set multilevel? if os.level_names.present? os.level_names.each_with_index do |level, l_index| - # prepend option set name so that level names are unique - # this avoids duplicate header errors - level_name = os_name + "_" + vanillify(level.values[0]) + level_name = unique_level_name(os_name, level.values[0]) # Append level name to qtype type_to_push = "#{qtype_converted} #{level_name}" @@ -384,8 +381,7 @@ def options_to_xls(option_sets, locales) if node.level.present? # per XLSform style, option sets with levels need to have the # list_name replaced with the level name to distinguish each row. - # prepend unique identifier to avoid duplicate header errors - listname_to_push = vanillify(os.name) + "_" + node.level_name + listname_to_push = unique_level_name(os.name, node.level_name) # Only attempt to access node ancestors if they exist if node.ancestry_depth > 1 @@ -422,9 +418,7 @@ def options_to_xls(option_sets, locales) # omit last entry (lowest level) if os.level_names.present? os.level_names[0..-2].each do |level| - - # prepend unique identifier - header_row.push(vanillify(os.name) + '_' + vanillify(level.values[0])) + header_row.push(unique_level_name(os.name, level.values[0])) # increment column counter column_counter += 1 @@ -439,6 +433,12 @@ def options_to_xls(option_sets, locales) os_matrix.insert(0, header_row) end + # prepend option set name so that level names are unique + # this avoids duplicate header errors + def unique_level_name(os_name, level_name) + "#{vanillify(os_name)}_#{vanillify(level_name)}" + end + # recursively remove pesky characters and replace spaces with underscores # for XLSForm compatibility def vanillify(input)