From c3db2895b5b57914d3f30f78efaa4740561f6b98 Mon Sep 17 00:00:00 2001 From: Luka Trovic Date: Fri, 16 Feb 2024 20:54:13 +0100 Subject: [PATCH] feat: autodetect data type during import Signed-off-by: Luka Trovic --- lib/Service/ColumnService.php | 6 ++-- lib/Service/ImportService.php | 53 ++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/Service/ColumnService.php b/lib/Service/ColumnService.php index be8c03e73..7bd41eaec 100644 --- a/lib/Service/ColumnService.php +++ b/lib/Service/ColumnService.php @@ -478,6 +478,7 @@ public function delete(int $id, bool $skipRowCleanup = false, ?string $userId = * @param int|null $tableId * @param int|null $viewId * @param array $titles example ['Test column 1', 'And so on', '3rd column title'] + * @param array $dataTypes example ['datetime', 'number', 'text'] * @param string|null $userId * @param bool $createUnknownColumns * @param int $countCreatedColumns @@ -488,7 +489,7 @@ public function delete(int $id, bool $skipRowCleanup = false, ?string $userId = * @throws NotFoundError * @throws PermissionError */ - public function findOrCreateColumnsByTitleForTableAsArray(?int $tableId, ?int $viewId, array $titles, ?string $userId, bool $createUnknownColumns, int &$countCreatedColumns, int &$countMatchingColumns): array { + public function findOrCreateColumnsByTitleForTableAsArray(?int $tableId, ?int $viewId, array $titles, array $dataTypes, ?string $userId, bool $createUnknownColumns, int &$countCreatedColumns, int &$countMatchingColumns): array { $result = []; if($userId === null) { @@ -522,7 +523,8 @@ 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.'); - $result[$i] = $this->create($userId, $tableId, $viewId, 'text', 'line', $title, false, $description, null, null, null, null, null, null, null, null, null, null, null, null, []); + $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, []); $countCreatedColumns++; } } diff --git a/lib/Service/ImportService.php b/lib/Service/ImportService.php index ce30abb16..adc22461b 100644 --- a/lib/Service/ImportService.php +++ b/lib/Service/ImportService.php @@ -18,6 +18,7 @@ use OCP\IUserManager; use OCP\Server; use PhpOffice\PhpSpreadsheet\IOFactory; +use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Worksheet\Row; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use Psr\Container\ContainerExceptionInterface; @@ -142,18 +143,17 @@ public function import(?int $tableId, ?int $viewId, string $path, bool $createMi * @throws PermissionError */ private function loop(Worksheet $worksheet): void { - $firstRow = true; - foreach ($worksheet->getRowIterator() as $row) { - if ($firstRow) { - $this->getColumns($row); - if (empty(array_filter($this->columns))) { - return; - } - $firstRow = false; - } else { - // parse row data - $this->createRow($row); - } + $firstRow = $worksheet->getRowIterator()->current(); + $secondRow = $worksheet->getRowIterator()->seek(2)->current(); + $this->getColumns($firstRow, $secondRow); + + if (empty(array_filter($this->columns))) { + return; + } + + foreach ($worksheet->getRowIterator(2) as $row) { + // parse row data + $this->createRow($row); } } @@ -212,9 +212,14 @@ private function createRow(Row $row): void { continue; } + $value = $cell->getValue(); + if ($this->columns[$i]->getType() === 'datetime') { + $value = Date::excelToDateTimeObject($value)->format('Y-m-d H:i'); + } + $data[] = [ 'columnId' => (int) $this->columns[$i]->getId(), - 'value' => json_decode($this->parseValueByColumnType($cell->getValue(), $this->columns[$i])), + 'value' => json_decode($this->parseValueByColumnType($value, $this->columns[$i])), ]; } try { @@ -234,26 +239,40 @@ private function createRow(Row $row): void { } /** - * @param Row $row + * @param Row $firstRow + * @param Row $secondRow * @throws InternalError * @throws NotFoundError * @throws PermissionError * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ - private function getColumns(Row $row): void { - $cellIterator = $row->getCellIterator(); + private function getColumns(Row $firstRow, Row $secondRow): void { + $cellIterator = $firstRow->getCellIterator(); + $secondRowCellIterator = $secondRow->getCellIterator(); $titles = []; + $dataTypes = []; 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'; + } } else { $this->logger->debug('No cell given or cellValue is empty while loading columns for importing'); $this->countErrors++; } + $secondRowCellIterator->next(); } try { - $this->columns = $this->columnService->findOrCreateColumnsByTitleForTableAsArray($this->tableId, $this->viewId, $titles, $this->userId, $this->createUnknownColumns, $this->countCreatedColumns, $this->countMatchingColumns); + $this->columns = $this->columnService->findOrCreateColumnsByTitleForTableAsArray($this->tableId, $this->viewId, $titles, $dataTypes, $this->userId, $this->createUnknownColumns, $this->countCreatedColumns, $this->countMatchingColumns); } catch (Exception $e) { throw new InternalError($e->getMessage()); }