From a93b81bda36e616a855b33b54f1c78d47cf93d75 Mon Sep 17 00:00:00 2001 From: Luka Trovic Date: Thu, 22 Feb 2024 14:02:58 +0100 Subject: [PATCH] feat: autodetect data type during import --- lib/Service/ColumnService.php | 25 +++++++++- lib/Service/ImportService.php | 87 +++++++++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 12 deletions(-) diff --git a/lib/Service/ColumnService.php b/lib/Service/ColumnService.php index 7bd41eaec..b65c3e532 100644 --- a/lib/Service/ColumnService.php +++ b/lib/Service/ColumnService.php @@ -523,8 +523,29 @@ public function findOrCreateColumnsByTitleForTableAsArray(?int $tableId, ?int $v // if column was not found if($result[$i] === '' && $createUnknownColumns) { $description = $this->l->t('This column was automatically created by the import service.'); - $subType = $dataTypes[$i] === 'text' ? 'line' : ''; - $result[$i] = $this->create($userId, $tableId, $viewId, $dataTypes[$i], $subType, $title, false, $description, null, null, null, null, null, null, null, null, null, null, null, null, []); + $result[$i] = $this->create( + $userId, + $tableId, + $viewId, + $dataTypes[$i]['type'], + $dataTypes[$i]['subtype'] ?? '', + $title, + false, + $description, + null, + null, + null, + $dataTypes[$i]['number_prefix'] ?? null, + $dataTypes[$i]['number_suffix'] ?? null, + null, + null, + null, + $dataTypes[$i]['number_decimals'] ?? null, + null, + $dataTypes[$i]['selection_default'] ?? null, + null, + [] + ); $countCreatedColumns++; } } diff --git a/lib/Service/ImportService.php b/lib/Service/ImportService.php index adc22461b..a2e8efd5c 100644 --- a/lib/Service/ImportService.php +++ b/lib/Service/ImportService.php @@ -17,6 +17,8 @@ use OCP\Files\NotPermittedException; use OCP\IUserManager; use OCP\Server; +use PhpOffice\PhpSpreadsheet\Cell\Cell; +use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Worksheet\Row; @@ -201,10 +203,13 @@ private function createRow(Row $row): void { continue; } + /** @var Column $column */ + $column = $this->columns[$i]; + // if cell is empty if(!$cell || $cell->getValue() === null) { $this->logger->info('Cell is empty while fetching rows data for importing.'); - if($this->columns[$i]->getMandatory()) { + if($column->getMandatory()) { $this->logger->warning('Mandatory column was not set'); $this->countErrors++; return; @@ -213,8 +218,12 @@ private function createRow(Row $row): void { } $value = $cell->getValue(); - if ($this->columns[$i]->getType() === 'datetime') { + if ($column->getType() === 'datetime') { $value = Date::excelToDateTimeObject($value)->format('Y-m-d H:i'); + } elseif ($column->getType() === 'number' && $column->getNumberSuffix() === '%') { + $value = $value * 100; + } elseif ($column->getType() === 'selection' && $column->getSubtype() === 'check') { + $value = $cell->getFormattedValue() === 'TRUE' ? 'true' : 'false'; } $data[] = [ @@ -255,16 +264,9 @@ private function getColumns(Row $firstRow, Row $secondRow): void { foreach ($cellIterator as $cell) { if ($cell && $cell->getValue() !== null && $cell->getValue() !== '') { $titles[] = $cell->getValue(); - $originDataType = $secondRowCellIterator->current()->getDataType(); // Convert data type to our data type - if (Date::isDateTime($secondRowCellIterator->current()) || $originDataType === 'd') { - $dataTypes[] = 'datetime'; - } elseif ($originDataType === 'n') { - $dataTypes[] = 'number'; - } else { - $dataTypes[] = 'text'; - } + $dataTypes[] = $this->parseColumnDataType($secondRowCellIterator->current()); } else { $this->logger->debug('No cell given or cellValue is empty while loading columns for importing'); $this->countErrors++; @@ -278,4 +280,69 @@ private function getColumns(Row $firstRow, Row $secondRow): void { } } + private function parseColumnDataType(Cell $cell): array { + $originDataType = $cell->getDataType(); + $value = $cell->getValue(); + $formattedValue = $cell->getFormattedValue(); + $dataType = [ + 'type' => 'text', + 'subtype' => 'line', + ]; + + if (Date::isDateTime($cell) || $originDataType === DataType::TYPE_ISO_DATE) { + $dataType = [ + 'type' => 'datetime', + ]; + } elseif ($originDataType === DataType::TYPE_NUMERIC) { + if (str_contains($formattedValue, '%')) { + $dataType = [ + 'type' => 'number', + 'number_decimals' => 2, + 'number_suffix' => '%', + ]; + } elseif (str_contains($formattedValue, '€')) { + $dataType = [ + 'type' => 'number', + 'number_decimals' => 2, + 'number_suffix' => '€', + ]; + } elseif (str_contains($formattedValue, 'EUR')) { + $dataType = [ + 'type' => 'number', + 'number_decimals' => 2, + 'number_suffix' => 'EUR', + ]; + } elseif (str_contains($formattedValue, '$')) { + $dataType = [ + 'type' => 'number', + 'number_decimals' => 2, + 'number_prefix' => '$', + ]; + } elseif (str_contains($formattedValue, 'USD')) { + $dataType = [ + 'type' => 'number', + 'number_decimals' => 2, + 'number_suffix' => 'USD', + ]; + } elseif (is_float($value)) { + $decimals = strlen(substr(strrchr($value, "."), 1)); + $dataType = [ + 'type' => 'number', + 'number_decimals' => $decimals, + ]; + } else { + $dataType = [ + 'type' => 'number', + ]; + } + } elseif ($originDataType === DataType::TYPE_BOOL) { + $dataType = [ + 'type' => 'selection', + 'subtype' => 'check', + 'selection_default' => 'false', + ]; + } + + return $dataType; + } }