def compute_prepend_numbers(inpath, col, outpath, rm_on_empty=False): """Compute numbers based on mini-language and prepend to all labels. This program highlights cells in the following two specific cases: (1) The numbering column says there should be a number in the label, but there is no number found in the original label. In this case, the number is add to the label. (2) The numbering column does not produce a number, but the original label has a number. In this case, the number is removed. Adding a number means to join the number, the string '. ', and the text of the cell. Args: inpath (str): The path where to find the source file. col (str): The name of the column where to find numbering. outpath (str): The path where to write the new xlsxfile. rm_on_empty (bool): Remove numbers that exist when numbering column is blank. """ xlsform = Xlsform(inpath) survey = xlsform['survey'] context = NumberingContext() for cell in survey.column(col): context.next(str(cell)) for i, header in enumerate(survey.column_headers()): if header.startswith('label') or header.startswith('ppp_label'): header_skipped = False for num, cell in zip(context.string_iter(), survey.column(i)): if not header_skipped: header_skipped = True continue if num: old_text = str(cell) cell_num, the_rest = utils.td_split_text(old_text) new_text = '. '.join((num, the_rest)) cell.value = new_text if not cell_num: # Highlight yellow for adding a number cell.set_highlight() elif new_text != old_text: # Highlight orange for changing a number cell.set_highlight('HL_ORANGE') elif cell and rm_on_empty: cell_num, the_rest = utils.td_split_text(str(cell)) if cell_num: cell.value = the_rest cell.set_highlight() xlsform.write_out(outpath)
def merge_translation_file(merge: List[str], translation_dict: TranslationDict, outfile: List[str], add: List[str], ignore: Set[str], carry: bool, no_diverse: bool): """Merge in translations to designated ODK files. Args: merge: The files to merge into translation_dict: The object with translation information outfile: Where to write the merged files. Should be the same length as `merge`. add: Languages to add ignore: Languages to ignore when merging carry: If true, carry text from the source language to the translations no_diverse: If true, do not insert a translation that has various choices """ for merge_source, merge_destination in zip(merge, outfile): xlsform = Xlsform(merge_source) xlsform.add_languages(add) xlsform.merge_translations(translation_dict, ignore, carry=carry, no_diverse=no_diverse) xlsform.write_out(merge_destination) print('Merged translations into file: "{}"'.format(merge_destination))
def test_form_language(self): """Form language is correctly determined.""" answers = (('language-default-none.xlsx', None), ('language-missing-default.xlsx', 'Dioula'), ('language-settings-default.xlsx', 'French')) for path, language in answers: form_path = os.path.join(self.FORM_DIR, path) xlsform = Xlsform(form_path) found = xlsform.form_language msg = 'Working with "{}"'.format(path) self.assertEqual(language, found, msg=msg)
def from_file(cls, path): """Create Odkform object from file in path. Args: path (str): The path for the source file of the ODK form, typically an '.xlsx' file meeting the XLSForm specification. Returns: Odkform """ xlsform = Xlsform(path) return cls(xlsform)
def create_translation_dict(xlsxfile: List[str], correct: List[str]) \ -> TranslationDict: """Create a translation dict from source Excel files. Args: xlsxfile: Paths to Excel files correct: Paths to Excel files that should be marked correct """ translation_dict = TranslationDict() extracted = set() for path in correct: if path in extracted: continue xlsform = Xlsform(path) translation_dict.extract_translations(xlsform, correct=True) extracted.add(path) for path in xlsxfile: if path in extracted: continue xlsform = Xlsform(path) translation_dict.extract_translations(xlsform) extracted.add(path) return translation_dict
def analytics_obj(xlsxfile): """Create an analytics object based on supplied path.""" xls = Xlsform(xlsxfile) form_id = xls.form_id form_title = xls.form_title prompts = get_filtered_survey_names(xls) tags = get_useful_tags(xls) today = str(datetime.date.today()) obj = { 'form_id': form_id, 'form_title': form_title, 'prompts': prompts, 'tags': tags, 'created': today, '~comment': 'END {}'.format(form_id) } return obj
def do_renumber(xlsform_path, renumbering_path, dry_run=False, all_columns=False): logging.info(f'Renumbering XLSForm {xlsform_path} with rules ' f'from {renumbering_path}') renumbering = RenumberMap(renumbering_path) xlsform = Xlsform(xlsform_path) check_label_numbers_match(xlsform) survey = xlsform['survey'] if all_columns: columns = list(range(len(survey.column_headers()))) else: columns = survey.translatable_columns(indices_only=True) cell_applications = [] for i, row in enumerate(survey): if i == 0: continue for j in columns: value = row[j].value applications = renumbering.applies_to(value) if applications: cell_applications.append((row[j], applications)) all_starts = set(renumbering.map.keys()) all_found_starts = set( itertools.chain.from_iterable(x for _, x in cell_applications)) missing = sorted(list(all_starts - all_found_starts)) if missing: logging.warning(f'Found items in renumber file but not ' f'in XLSForm: {missing}, count: {len(missing)}') change_count = 0 for cell, applications in cell_applications: old_value = cell.value new_value = renumbering.apply(old_value, applications) if not dry_run: cell.value = new_value if old_value != new_value: change_count += 1 cell.set_highlight() else: cell.set_highlight('HL_ORANGE') logging.info( f'Done renumbering XLSForm. Number of cell changes: {change_count}') return xlsform
def test_sheet_language(self): """Languages found in a sheet are correctly determined.""" answers = (('language-default-none.xlsx', { 'survey': [ None, 'Dioula', 'English', 'French', 'Fulfulde', 'Gourmantchema', 'Moore' ], 'choices': ['English', 'French'], 'settings': [] }), ) for path, answer in answers: form_path = os.path.join(self.FORM_DIR, path) xlsform = Xlsform(form_path) for sheet in xlsform: found = sheet.sheet_languages() name = sheet.name expected = answer[name] msg = 'Testing file "{}" and sheet "{}"'.format(path, name) self.assertEqual(expected, found, msg=msg)
def from_file(cls, path): """Create Odkform object from file in path. Args: path (str): The path for the source file of the ODK form, typically an '.xlsx' file meeting the XLSForm specification. Returns: Odkform """ xlsform = Xlsform(path) odkform = cls(xlsform) if xlsform.warnings: msg = 'Warning! File {} contained spreadsheet errors. This may ' \ 'or may not cause problems in the resulting converted ' \ 'files. Just to be on the safe side, you may want to open ' \ 'the original spreadsheet file, take a look at the errors,' \ ' and fix and convert again if you feel the need.\nThe ' \ 'errors found are as follows:\n{}'\ .format(odkform.title, xlsform.warnings) print(msg, file=stderr) return odkform