Skip to content

Commit

Permalink
feat: autodetect data type during import
Browse files Browse the repository at this point in the history
Signed-off-by: Luka Trovic <luka@nextcloud.com>
  • Loading branch information
luka-nextcloud committed Feb 22, 2024
1 parent 166ef28 commit c3db289
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 19 deletions.
6 changes: 4 additions & 2 deletions lib/Service/ColumnService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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++;
}
}
Expand Down
53 changes: 36 additions & 17 deletions lib/Service/ImportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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());
}
Expand Down

0 comments on commit c3db289

Please sign in to comment.