{"id":18577930,"url":"https://github.com/gnucoop/formconv","last_synced_at":"2025-04-10T10:30:56.320Z","repository":{"id":96920346,"uuid":"192905400","full_name":"gnucoop/formconv","owner":"gnucoop","description":"XLS to Ajf JSON converter","archived":false,"fork":false,"pushed_at":"2025-01-27T11:44:27.000Z","size":947,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T19:22:14.066Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gnucoop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-20T11:11:21.000Z","updated_at":"2025-01-27T11:44:31.000Z","dependencies_parsed_at":"2025-01-27T12:42:51.894Z","dependency_job_id":null,"html_url":"https://github.com/gnucoop/formconv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gnucoop%2Fformconv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gnucoop%2Fformconv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gnucoop%2Fformconv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gnucoop%2Fformconv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gnucoop","download_url":"https://codeload.github.com/gnucoop/formconv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248199136,"owners_count":21063641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T23:32:08.128Z","updated_at":"2025-04-10T10:30:56.307Z","avatar_url":"https://github.com/gnucoop.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"formconv compiles [xlsform](http://xlsform.org/en/) excel files to ajf, a json-based format used at gnucoop to describe forms.\nThe tool can be installed with:\n\n```go get github.com/gnucoop/formconv```\n\nand used as:\n\n```formconv form1.xlsx form2.xls form3.xls```\n\nformconv implements a (slightly customized) subset of the xlsform specification.\nSupported features are listed in this document.\n\n## Introduction to xlsforms\n\n[Xlsform](http://xlsform.org/en/) is a standard that allows authoring forms in excel.\nA xlsform excel file has two main sheets: \"survey\" and \"choices\".\nThe survey sheet describes the content of the form, while \"choices\" is used to define answers for single- or multiple-choice questions.\nEmpty rows and columns are ignored.\nA simple example is given below.\n\nSurvey sheet:\n\n|type                     |name       |label      |\n|-------------------------|-----------|-----------|\n|begin group              |info       |General Information |\n|text                     |username   |Your name: |\n|select_one yes_no        |pizza      |Do you like pizza? |\n|select_multiple mealtime |mealtimes  |When do you have pizza? |\n|end group                |           |           |\n\nChoices sheet:\n\n|list name |name      |label     |\n|----------|----------|----------|\n|yes_no    |yes       |Yes       |\n|yes_no    |no        |No        |\n|mealtime  |breakfast |Breakfast |\n|mealtime  |lunch     |Lunch     |\n|mealtime  |dinner    |Dinner    |\n\n## Question types\n\nThe following table lists the supported question types.\n\n|Question type   |Ajf field type  |Description     |\n|----------------|----------------|----------------|\n|decimal         |number          |64-bit floating point number |\n|integer         |number          |A number with the added constraint of being an integer |\n|range           |range           |A number in a specific [range](#range) |\n|text            |string          |Free text response |\n|boolean         |boolean         |Boolean answer (a checkbox) |\n|select_one      |single choice   |Single choice answer |\n|select_multiple |multiple choice |Multiple choice answer |\n|note            |empty           |Inserts an HTML note in the form |\n|date            |date input      |A date          |\n|time            |time            |Time            |\n|table           |table           |A [table](#tables) |\n|barcode         |barcode         |Scan a barcode  |\n|geopoint        |geolocation     |A location as GPS coordinates |\n|file            |file            |Upload a file   |\n|image           |image           |Take a picture or upload an image |\n|video           |video url       |The url of a video |\n|calculate       |formula         |Perform a [calculation](#calculation) |\n\n## Hints\n\nHints can be provided to help the user answer some questions of the form:\n\n|type      |name       |label                           |hint      |\n|----------|-----------|--------------------------------|----------|\n|text      |store_name |What is the name of this store? |Look at the signboard |\n\n## Required\n\nIt is possible to flag questions as required, so that the user won't be able to submit the form without providing a value:\n\n|type      |name      |label               |required  |required_message |\n|----------|----------|--------------------|----------|-----------------|\n|text      |color     |Your favorite color |yes       |This field is mandatory |\n\nThe required_message column is optional.\n\n## Default values\n\nThe default value for a field can be provided as a [formula](#formulas) with the \"default\" column:\n\n|type      |name          |label              |default   |\n|----------|--------------|-------------------|----------|\n|boolean   |priority_ship |Priority Shipping: |False     |\n\n## Readonly\n\nFields can be made read-only using the \"readonly\" column, which translates to `editable: false` in ajf:\n\n|type      |name       |label       |readonly  |\n|----------|-----------|------------|----------|\n|date      |event_date |Event Date: |yes       |\n\nAs an extension to the xlsform standard, an entire group can be made conditionally read-only,\nby providing a boolean [formula](#formulas) in the readonly column of the group.\n\n## Grouping\n\nQuestions can be grouped, as shown in the [introductory example](#introduction-to-xlsforms); groups can be nested.\n\nAjf forms have the peculiarity of being organized in slides, which has implications on how groups are handled.\nTop-level groups are translated to slides, while inner groups are translated to ajf group nodes.\nSlides will be created automatically for sequences of questions that aren't grouped.\n\n## Repeats\n\nRepeats give the user the possibility to repeat a group of questions:\n\n|type         |name         |label        |repeat_count |\n|-------------|-------------|-------------|-------------|\n|begin repeat |child_repeat |Answer the following questions for each one of your children |20 |\n|text         |name         |Child's name |             |\n|decimal      |birthweight  |Child's birthweight |      |\n|end repeat   |             |             |             |\n\nWhen specified, `repeat_count` defines an upper bound to how many times the group can be repeated.\nRepeats cannot be nested inside other repeats or groups.\n\n## Constraints\n\nConstraints can be used to ensure data quality in the form:\n\n|type      |name      |label            |constraint |constraint_message        |\n|----------|----------|-----------------|-----------|--------------------------|\n|integer   |age       |How old are you? |`. \u003c 150`  |Age must be less than 150 |\n\nThe dot in the constraint formula refers to the value of the question.\nThe constraint message is optional.\n\n## Relevant\n\nThe relevant column allows skipping a question or making and additional question appear based on the response to a previous question:\n\n|type               |name      |label             |relevant             |\n|-------------------|----------|------------------|---------------------|\n|select_one cat_dog |pet_type  |Are you a cat or a dog person? |        |\n|text               |cat_name  |Name of your cat: |`${pet_type} = \"cat\"`|\n|text               |dog_name  |Name of your dog: |`${pet_type} = \"dog\"`|\n\nThe feature can also be applied to groups.\n\nAs an extension to the xlsform standard, the column permissions_relevant allows to specify if the current user has permission to see the question or group:\n\n|type      |name           |label               |relevant     |permissions_relevant |\n|----------|---------------|--------------------|-------------|---------------------|\n|text      |driver_license |Driver License Code |`${age} \u003e 18`|`js: isUserInGroup('drivers', dino_form_info)`|\n\n## Range\n\nA range input restricts a numeric input to a specific range.\nIn this example form, the user can provide a rating from 1 to 5:\n\n|type      |name      |label                         |parameters           |\n|----------|----------|------------------------------|---------------------|\n|range     |rating    |How do you rate our services? |start=1 end=5 step=1 |\n\nThe default values for the parameters are: start=0 end=10 step=1.\n\n## Appearance\n\nThe appearance column allows to modify the appearance of some fields,\nas described in the following table:\n\n|question type               |appearance |description             |\n|----------------------------|-----------|------------------------|\n|text                        |multiline  |Shows a bigger text box |\n|select_one, select_multiple |minimal    |Choices appear in a pull-down menu    |\n|image                       |signature  |Presents a canvas to draw a signature |\n\n## Formulas\n\nFormulas are used in the default, constraint, relevant and calculation columns.\nformconv supports a subset of xlsform formulas.\nIn particular, the features involving nodesets are omitted, as ajf doesn't have an equivalent concept.\n\nFormulas are expressions composed of constants, question references, operators and functions.\n\nSince ajf works with JavaScript expressions, formulas are parsed and converted to JavaScript (with no semantical analysis).\nIt is possible to write formulas directly in JavaScript, by adding the prefix `js:`, as in `js: Date.now()`.\n\n### Constants\n\nConstants can be numbers, strings (delimited by 'single' or \"double\" quotes) or booleans (`True` or `False`).\n\n### Question References\n\nTo reference the value provided as answer to a question, use the expression `${question_name}`.\nThe name must be a valid javascript identifier.\n`.` can be used to refer to the current question, as seen in the [constraint example](#constraints).\n\n### Operators\n\nThe following table lists the supported operators with their corresponding JavaScript implementation:\n\n|                |   |   |   |     |     |     |     |   |    |   |    |     |    |\n|----------------|---|---|---|-----|-----|-----|-----|---|----|---|----|-----|----|\n| Formula op:    |`+`|`-`|`*`|`div`|`mod`|`=`  |`!=` |`\u003e`|`\u003e=`|`\u003c`|`\u003c=`|`and`|`or`|\n| JavaScript op: |`+`|`-`|`*`|`/`  |`%`  |`===`|`!==`|`\u003e`|`\u003e=`|`\u003c`|`\u003c=`|`\u0026\u0026` |`ǀǀ`|\n\nThe precedence of operators is as defined by JavaScript operators.\nRound parentheses can be used in formulas.\n\n### Functions\n\n#### String Manipulation Functions\n\n|Formula function         |JavaScript translation |\n|-------------------------|-----------------------|\n|`regex(s, re)`           |`((s).match(re) !== null)`|\n|`contains(s, t)`         |`(s).includes(t)`      |\n|`starts-with(s, t)`      |`(s).startsWith(t)`    |\n|`ends-with(s, t)`        |`(s).endsWith(t)`      |\n|`substr(s, start[, end])`|`(s).substring(start[, end])`|\n|`string-length(s)`       |`(s).length`           |\n|`concat(s, t...)`        |`(s).concat(t...)`     |\n|`string(x)`              |`String(x)`            |\n\n#### Mathematical Functions\n\nThe 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`.\n\nOther functions dealing with numbers:\n\n|Formula function |JavaScript/ajf translation |\n|-----------------|---------------------------|\n|`int(x)`         |`Math.floor(x)`            |\n|`round(x, d)`    |`round(x, d)` (ajf function, rounds `x` to `d` digits) |\n|`exp10(x)`       |`Math.pow(10, x)`          |\n|`pi()`           |`Math.PI`                  |\n|`number(x)`      |`Number(x)`                |\n\n#### Boolean functions\n\n|Formula function |JavaScript translation |\n|-----------------|-----------------------|\n|`not(x)`         |`!(x)`                 |\n|`true()`         |`true`                 |\n|`false()`        |`false`                |\n|`boolean(x)`     |`Boolean(x)`           |\n\n#### Other functions\n\n|Formula function        |JavaScript/ajf translation |Description |\n|------------------------|---------------------------|------------|\n|`if(cond, then, else)`  |`(cond ? then : else)`     |            |\n|`selected(${mul}, val)` |`valueInChoice(mul, val)`  |returns true if `val` has been selected \u003cbr\u003e in the multiple choice question `mul` |\n|`count-selected(${mul})`|`(mul).length`             |returns the number of options chosen \u003cbr\u003e in the multiple choice question `mul` |\n\n## Calculation\n\nCalculations can be performed using the values of other questions:\n\n|type      |name      |label               |calculation       |\n|----------|----------|--------------------|------------------|\n|decimal   |amount    |Price of your meal: |                  |\n|calculate |tip       |5% tip is:          |`${amount} * 0.05`|\n\nThe results of calculations will appear as read-only fields in the form.\n\n## Choice filters\n\nThe 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:\n\n|type                 |name         |label                         |choice_filter |\n|---------------------|-------------|------------------------------|--------------|\n|select_one countries |user_country |In which country do you live? |              |\n|select_one cities    |user_city    |In which city do you live?    |`country = ${user_country}`|\n\nWith the `choices` sheet containing the appropriate information to perform the filtering:\n\n|list name |name      |label     |country   |\n|----------|----------|----------|----------|\n|countries |italy     |Italy     |          |\n|countries |germany   |Germany   |          |\n|cities    |milan     |Milan     |italy     |\n|cities    |rome      |Rome      |italy     |\n|cities    |berlin    |Berlin    |germany   |\n|cities    |hamburg   |Hamburg   |germany   |\n\nIn this case, the user-defined column \"country\" has been added to the choices sheet.\nAny column name can be used, as long as it is a valid identifier\n(as it has to be referenced as an identifier in the `choice_filter` formula)\n\n## Tables\n\nAjf allows organizing form inputs in tables.\n\nTo define a table, use the field type \"table\":\n\n|type      |name      |label     |\n|----------|----------|----------|\n|table     |attendees |Attendees |\n\nThen, create an excel sheet named like the table (\"attendees\", in this case):\n\n|          |number Males |number Females |number Total |\n|----------|-------------|---------------|-------------|\n|Day 1     |             |               |`${attendees__0__0} + ${attendees__0__1}`|\n|Day 2     |             |               |`${attendees__1__0} + ${attendees__1__1}`|\n|Day 3     |             |               |`${attendees__2__0} + ${attendees__2__1}`|\n\nThe column headers must be in the format \"type label\",\nwhere type can be \"text\", \"number\" or \"date\".\n\nSome of the fields can be computed as a function of other cells in the table itself,\nas shown in the example.\n\nThe sheet must not contain empty columns or rows in leading position nor mid-table.\n\n## Multiple language support\n\nA form may include multiple languages with the following syntax:\n\n|type      |name      |label            |label::ESP            |label::ITA       |\n|----------|----------|-----------------|----------------------|-----------------|\n|integer   |age       |How old are you? |¿Cuántos años tienes? |Quanti anni hai? |\n\nThe columns that support multiple languages are: label, hint, constraint_message and required_message\n(including label in the choices sheet).\n\n## Form tags\n\nTags are (label, value) pairs that can be used in ajf to highlight some fields of a compiled form.\nThe 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.\nTags can be specified in formconv using a \"settings\" sheet with the following syntax:\n\n|tag label |tag value |\n|----------|----------|\n|Gender    |gender    |\n|Age       |age       |\n\nSuch tags will be added to the `stringIdentifier` list of tags in the resulting ajf form.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgnucoop%2Fformconv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgnucoop%2Fformconv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgnucoop%2Fformconv/lists"}