Categorygithub.com/gnucoop/formconv
repositorypackage
0.0.0-20240826142334-1c9e97762707
Repository: https://github.com/gnucoop/formconv.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author

# README

formconv compiles xlsform excel files to ajf, a json-based format used at gnucoop to describe forms. The tool can be installed with:

go get github.com/gnucoop/formconv

and used as:

formconv form1.xlsx form2.xls form3.xls

formconv implements a (slightly customized) subset of the xlsform specification. Supported features are listed in this document.

Introduction to xlsforms

Xlsform is a standard that allows authoring forms in excel. A xlsform excel file has two main sheets: "survey" and "choices". The survey sheet describes the content of the form, while "choices" is used to define answers for single- or multiple-choice questions. Empty rows and columns are ignored. A simple example is given below.

Survey sheet:

typenamelabel
begin groupinfoGeneral Information
textusernameYour name:
select_one yes_nopizzaDo you like pizza?
select_multiple mealtimemealtimesWhen do you have pizza?
end group

Choices sheet:

list namenamelabel
yes_noyesYes
yes_nonoNo
mealtimebreakfastBreakfast
mealtimelunchLunch
mealtimedinnerDinner

Question types

The following table lists the supported question types.

Question typeAjf field typeDescription
decimalnumber64-bit floating point number
integernumberA number with the added constraint of being an integer
rangerangeA number in a specific range
textstringFree text response
booleanbooleanBoolean answer (a checkbox)
select_onesingle choiceSingle choice answer
select_multiplemultiple choiceMultiple choice answer
noteemptyInserts an HTML note in the form
datedate inputA date
timetimeTime
tabletableA table
barcodebarcodeScan a barcode
geopointgeolocationA location as GPS coordinates
filefileUpload a file
imageimageTake a picture or upload an image
videovideo urlThe url of a video
calculateformulaPerform a calculation

Hints

Hints can be provided to help the user answer some questions of the form:

typenamelabelhint
textstore_nameWhat is the name of this store?Look at the signboard

Required

It is possible to flag questions as required, so that the user won't be able to submit the form without providing a value:

typenamelabelrequiredrequired_message
textcolorYour favorite coloryesThis field is mandatory

The required_message column is optional.

Default values

The default value for a field can be provided as a formula with the "default" column:

typenamelabeldefault
booleanpriority_shipPriority Shipping:False

Readonly

Fields can be made read-only using the "readonly" column, which translates to editable: false in ajf:

typenamelabelreadonly
dateevent_dateEvent Date:yes

As an extension to the xlsform standard, an entire group can be made conditionally read-only, by providing a boolean formula in the readonly column of the group.

Grouping

Questions can be grouped, as shown in the introductory example; groups can be nested.

Ajf forms have the peculiarity of being organized in slides, which has implications on how groups are handled. Top-level groups are translated to slides, while inner groups are translated to ajf group nodes. Slides will be created automatically for sequences of questions that aren't grouped.

Repeats

Repeats give the user the possibility to repeat a group of questions:

typenamelabelrepeat_count
begin repeatchild_repeatAnswer the following questions for each one of your children20
textnameChild's name
decimalbirthweightChild's birthweight
end repeat

When specified, repeat_count defines an upper bound to how many times the group can be repeated. Repeats cannot be nested inside other repeats or groups.

Constraints

Constraints can be used to ensure data quality in the form:

typenamelabelconstraintconstraint_message
integerageHow old are you?. < 150Age must be less than 150

The dot in the constraint formula refers to the value of the question. The constraint message is optional.

Relevant

The relevant column allows skipping a question or making and additional question appear based on the response to a previous question:

typenamelabelrelevant
select_one cat_dogpet_typeAre you a cat or a dog person?
textcat_nameName of your cat:${pet_type} = "cat"
textdog_nameName of your dog:${pet_type} = "dog"

The feature can also be applied to groups.

Range

A range input restricts a numeric input to a specific range. In this example form, the user can provide a rating from 1 to 5:

typenamelabelparameters
rangeratingHow do you rate our services?start=1 end=5 step=1

The default values for the parameters are: start=0 end=10 step=1.

Appearance

The appearance column allows to modify the appearance of some fields, as described in the following table:

question typeappearancedescription
textmultilineShows a bigger text box
select_one, select_multipleminimalChoices appear in a pull-down menu
imagesignaturePresents a canvas to draw a signature

Formulas

Formulas are used in the default, constraint, relevant and calculation columns. formconv supports a subset of xlsform formulas. In particular, the features involving nodesets are omitted, as ajf doesn't have an equivalent concept.

Formulas are expressions composed of constants, question references, operators and functions.

Since ajf works with JavaScript expressions, formulas are parsed and converted to JavaScript (with no semantical analysis). It is possible to write formulas directly in JavaScript, by adding the prefix js:, as in js: Date.now().

Constants

Constants can be numbers, strings (delimited by 'single' or "double" quotes) or booleans (True or False).

Question References

To reference the value provided as answer to a question, use the expression ${question_name}. The name must be a valid javascript identifier. . can be used to refer to the current question, as seen in the constraint example.

Operators

The following table lists the supported operators with their corresponding JavaScript implementation:

Formula op:+-*divmod=!=>>=<<=andor
JavaScript op:+-*/%===!==>>=<<=&&ǀǀ

The precedence of operators is as defined by JavaScript operators. Round parentheses can be used in formulas.

Functions

String Manipulation Functions

Formula functionJavaScript translation
regex(s, re)((s).match(re) !== null)
contains(s, t)(s).includes(t)
starts-with(s, t)(s).startsWith(t)
ends-with(s, t)(s).endsWith(t)
substr(s, start[, end])(s).substring(start[, end])
string-length(s)(s).length
concat(s, t...)(s).concat(t...)
string(x)String(x)

Mathematical Functions

The following functions are available in formulas and are translated to the equivalent Math functions in JavaScript: max, min, pow, log, log10, abs, sin, cos, tan, asin, acos, atan, atan2, sqrt, exp, random.

Other functions dealing with numbers:

Formula functionJavaScript/ajf translation
int(x)Math.floor(x)
round(x, d)round(x, d) (ajf function, rounds x to d digits)
exp10(x)Math.pow(10, x)
pi()Math.PI
number(x)Number(x)

Boolean functions

Formula functionJavaScript translation
not(x)!(x)
true()true
false()false
boolean(x)Boolean(x)

Other functions

Formula functionJavaScript/ajf translationDescription
if(cond, then, else)(cond ? then : else)
selected(${mul}, val)valueInChoice(mul, val)returns true if val has been selected
in the multiple choice question mul
count-selected(${mul})(mul).lengthreturns the number of options chosen
in the multiple choice question mul

Calculation

Calculations can be performed using the values of other questions:

typenamelabelcalculation
decimalamountPrice of your meal:
calculatetip5% tip is:${amount} * 0.05

The results of calculations will appear as read-only fields in the form.

Choice filters

The list of values for a single- or multiple-choice question can be filtered depending on the answer to previous questions, using the choice_filter column:

typenamelabelchoice_filter
select_one countriesuser_countryIn which country do you live?
select_one citiesuser_cityIn which city do you live?country = ${user_country}

With the choices sheet containing the appropriate information to perform the filtering:

list namenamelabelcountry
countriesitalyItaly
countriesgermanyGermany
citiesmilanMilanitaly
citiesromeRomeitaly
citiesberlinBerlingermany
citieshamburgHamburggermany

In this case, the user-defined column "country" has been added to the choices sheet. Any column name can be used, as long as it is a valid identifier (as it has to be referenced as an identifier in the choice_filter formula)

Tables

Ajf allows organizing form inputs in tables.

To define a table, use the field type "table":

typenamelabel
tableattendeesAttendees

Then, create an excel sheet named like the table ("attendees", in this case):

number Malesnumber Femalesnumber Total
Day 1${attendees__0__0} + ${attendees__0__1}
Day 2${attendees__1__0} + ${attendees__1__1}
Day 3${attendees__2__0} + ${attendees__2__1}

The column headers must be in the format "type label", where type can be "text", "number" or "date".

Some of the fields can be computed as a function of other cells in the table itself, as shown in the example.

The sheet must not contain empty columns or rows in leading position nor mid-table.

Multiple language support

A form may include multiple languages with the following syntax:

typenamelabellabel::ESPlabel::ITA
integerageHow old are you?¿Cuántos años tienes?Quanti anni hai?

The columns that support multiple languages are: label, hint, constraint_message and required_message (including label in the choices sheet).

Form tags

Tags are (label, value) pairs that can be used in ajf to highlight some fields of a compiled form. The tag label is a string that provides a description of the tag, while the tag value is the identifier of a field in the form. Tags can be specified in formconv using a "settings" sheet with the following syntax:

tag labeltag value
Gendergender
Ageage

Such tags will be added to the stringIdentifier list of tags in the resulting ajf form.