diff --git a/README.md b/README.md index 6672eb6..5332903 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Generation has to be invoked as additional gradle task. Java 1.8 is required. * comments * formatted strings - `formatted` XML attribute * default locale specification - `tools:locale` + * evaluate cell formulas ## Applying plugin ### Gradle 2.1+ @@ -153,6 +154,7 @@ possible values: * `sheetName` - default=``, name of the sheet to be processed, only one can be specified, ignored if `useAllSheets` is set to true * `useAllSheets` - default=`false`, if set to true all sheets are processed and `sheetName` is ignored +* `evaluateFormulas` - default=`false`, if set to true evaluates formulas in cells #### Advanced options: * `ignorableColumns` - default=`[]`, columns from that list will be ignored during parsing. List should diff --git a/src/main/groovy/pl/droidsonroids/gradle/localization/ConfigExtension.groovy b/src/main/groovy/pl/droidsonroids/gradle/localization/ConfigExtension.groovy index 6d49195..6370f76 100644 --- a/src/main/groovy/pl/droidsonroids/gradle/localization/ConfigExtension.groovy +++ b/src/main/groovy/pl/droidsonroids/gradle/localization/ConfigExtension.groovy @@ -18,6 +18,7 @@ class ConfigExtension { boolean convertTripleDotsToHorizontalEllipsis = true boolean escapeSlashes = true boolean useAllSheets = false + boolean evaluateFormulas = false TagEscapingStrategy tagEscapingStrategy = TagEscapingStrategy.IF_TAGS_ABSENT Normalizer.Form normalizationForm = Normalizer.Form.NFC String defaultColumnName = 'default' diff --git a/src/main/groovy/pl/droidsonroids/gradle/localization/ParserEngine.groovy b/src/main/groovy/pl/droidsonroids/gradle/localization/ParserEngine.groovy index c93618a..a80756a 100644 --- a/src/main/groovy/pl/droidsonroids/gradle/localization/ParserEngine.groovy +++ b/src/main/groovy/pl/droidsonroids/gradle/localization/ParserEngine.groovy @@ -58,7 +58,7 @@ class ParserEngine { mParser = config.csvStrategy ? new CSVInnerParser(reader, config.csvStrategy) : new CSVInnerParser(reader) } else { def isXLS = sourceType == SourceType.XLS - mParser = new XLSXParser((InputStream) mCloseableInput, isXLS, config.sheetName, config.useAllSheets) + mParser = new XLSXParser((InputStream) mCloseableInput, isXLS, config.sheetName, config.useAllSheets, config.evaluateFormulas) } } diff --git a/src/main/groovy/pl/droidsonroids/gradle/localization/XLSXParser.groovy b/src/main/groovy/pl/droidsonroids/gradle/localization/XLSXParser.groovy index d82ff2d..ce7c8fe 100644 --- a/src/main/groovy/pl/droidsonroids/gradle/localization/XLSXParser.groovy +++ b/src/main/groovy/pl/droidsonroids/gradle/localization/XLSXParser.groovy @@ -1,34 +1,32 @@ package pl.droidsonroids.gradle.localization import org.apache.poi.hssf.usermodel.HSSFWorkbook -import org.apache.poi.ss.usermodel.Row -import org.apache.poi.ss.usermodel.Sheet -import org.apache.poi.ss.usermodel.Workbook +import org.apache.poi.ss.usermodel.* import org.apache.poi.xssf.usermodel.XSSFWorkbook class XLSXParser implements Parser { private Map mAllSheets - XLSXParser(InputStream inputStream, boolean isXls, String sheetName, boolean useAllSheets) { + XLSXParser(InputStream inputStream, boolean isXls, String sheetName, boolean useAllSheets, boolean evaluateFormulas) { Workbook workbook = isXls ? new HSSFWorkbook(inputStream) : new XSSFWorkbook(inputStream) workbook.setMissingCellPolicy(Row.MissingCellPolicy.CREATE_NULL_AS_BLANK) - + FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator() if (useAllSheets) { mAllSheets = new HashMap<>(workbook.numberOfSheets) for (Sheet sheet : workbook.sheetIterator()) { - mAllSheets.put(sheet.getSheetName(), getAllValues(sheet)) + mAllSheets.put(sheet.getSheetName(), getAllValues(sheet, evaluator, evaluateFormulas)) } } else { mAllSheets = new HashMap<>(1) Sheet sheet = sheetName ? workbook.getSheet(sheetName) : workbook.getSheetAt(0) if (sheet == null) throw new IllegalArgumentException("Sheet $sheetName does not exist") - mAllSheets.put(null, getAllValues(sheet)) + mAllSheets.put(null, getAllValues(sheet, evaluator, evaluateFormulas)) } } - static String[][] getAllValues(Sheet sheet) { + static String[][] getAllValues(Sheet sheet, FormulaEvaluator evaluator, boolean evaluateFormulas) { String[][] allCells = new String[sheet.lastRowNum + 1][] for (int i = 0; i <= sheet.lastRowNum; i++) { Row row = sheet.getRow(i) @@ -36,7 +34,9 @@ class XLSXParser implements Parser { continue allCells[i] = new String[row.lastCellNum] for (int j = 0; j < row.lastCellNum; j++) { - allCells[i][j] = row.getCell(j).toString() ?: "" + Cell cell = row.getCell(j) + if (evaluateFormulas) evaluator.evaluateInCell(cell) + allCells[i][j] = cell.toString() ?: "" } } return allCells diff --git a/src/test/groovy/pl/droidsonroids/gradle/localization/ParseXLSXTest.groovy b/src/test/groovy/pl/droidsonroids/gradle/localization/ParseXLSXTest.groovy index 39ae776..aaf4a98 100644 --- a/src/test/groovy/pl/droidsonroids/gradle/localization/ParseXLSXTest.groovy +++ b/src/test/groovy/pl/droidsonroids/gradle/localization/ParseXLSXTest.groovy @@ -82,4 +82,37 @@ class ParseXLSXTest extends LocalizationPluginTestBase { config.xlsFileURI = 'https://docs.google.com/a/droidsonroids.pl/spreadsheets/d/1sfE3Zk_7syHpq3HPKYQ9gRidm1W7c1IjIfdH1R8z9m4/export?format=xlsx' parseTestFile(config) } + + @Test + void testXlsxFileWithFormulas() { + def name = 'valid_formulas.xlsx' + + ConfigExtension config = new ConfigExtension() + config.xlsFileURI = getClass().getResource(name).toString() + config.allowEmptyTranslations = true + config.skipInvalidName = true + config.skipDuplicatedName = true + config.evaluateFormulas = true + config.defaultColumnName = 'EN' + config.nameColumnName = 'Android' + config.ignorableColumns.add('WinPhone') + config.ignorableColumns.add('iOS') + config.ignorableColumns.add('END') + config.defaultLocaleQualifier = 'en' + config.useAllSheets = true + + def resDir = parseTestFile(config) + + resDir.traverse(type: FileType.FILES) { + def filePath = it.path.replace(resDir.path, '') + def expectedFileURL = getClass().getResource("parsed_valid_formulas_xlsx/$filePath") + def diff = DiffBuilder.compare(Input.fromFile(it)) + .withTest(Input.fromURL(expectedFileURL)) + .ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes)) + .checkForSimilar() + .build() + assertThat(diff.hasDifferences()).as('file: %s is different than expected %s', filePath, diff.toString()).isFalse() + } + } } diff --git a/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/additional.xml b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/additional.xml new file mode 100644 index 0000000..c5d6803 --- /dev/null +++ b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/additional.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/main.xml b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/main.xml new file mode 100644 index 0000000..c5f3c2d --- /dev/null +++ b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values-pl/main.xml @@ -0,0 +1,9 @@ + + + Plik + + + krowy + krowa + + \ No newline at end of file diff --git a/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/additional.xml b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/additional.xml new file mode 100644 index 0000000..383f15b --- /dev/null +++ b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/additional.xml @@ -0,0 +1,4 @@ + + + koral-- + \ No newline at end of file diff --git a/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/main.xml b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/main.xml new file mode 100644 index 0000000..793d65f --- /dev/null +++ b/src/test/resources/pl/droidsonroids/gradle/localization/parsed_valid_formulas_xlsx/values/main.xml @@ -0,0 +1,17 @@ + + + Application + File + %d %s + + monday, tuesday, wednesday + + cows + cow + + + monday + tuesday + wednesday + + diff --git a/src/test/resources/pl/droidsonroids/gradle/localization/valid_formulas.xlsx b/src/test/resources/pl/droidsonroids/gradle/localization/valid_formulas.xlsx new file mode 100644 index 0000000..ffe9b71 Binary files /dev/null and b/src/test/resources/pl/droidsonroids/gradle/localization/valid_formulas.xlsx differ