- Removido README.md padrão do Laravel (backend) - Removidos scripts de deploy (não mais necessários) - Atualizado copilot-instructions.md para novo fluxo - Adicionada documentação de auditoria do servidor - Sincronizado código de produção com repositório Novo workflow: - Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney) - Mudanças PHP são instantâneas - Mudanças React requerem 'npm run build' - Commit após validação funcional
165 lines
5.2 KiB
PHP
Executable File
165 lines
5.2 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Services\Import;
|
|
|
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
|
|
|
class ExcelParser implements FileParserInterface
|
|
{
|
|
protected static array $supportedExtensions = ['xlsx', 'xls'];
|
|
|
|
/**
|
|
* Parse the Excel file and return all data
|
|
*/
|
|
public function parse(string $filePath, array $options = []): array
|
|
{
|
|
$headerRow = $options['header_row'] ?? 0;
|
|
$dataStartRow = $options['data_start_row'] ?? 1;
|
|
|
|
$spreadsheet = IOFactory::load($filePath);
|
|
$worksheet = $spreadsheet->getActiveSheet();
|
|
|
|
$data = [];
|
|
$headers = [];
|
|
|
|
foreach ($worksheet->getRowIterator() as $rowIndex => $row) {
|
|
$rowData = [];
|
|
$cellIterator = $row->getCellIterator();
|
|
$cellIterator->setIterateOnlyExistingCells(false);
|
|
|
|
foreach ($cellIterator as $cell) {
|
|
$value = $cell->getCalculatedValue();
|
|
// Tratar valores de data do Excel
|
|
if (\PhpOffice\PhpSpreadsheet\Shared\Date::isDateTime($cell)) {
|
|
try {
|
|
$dateValue = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
|
|
$value = $dateValue->format('d/m/Y');
|
|
} catch (\Exception $e) {
|
|
// Manter valor original se não conseguir converter
|
|
}
|
|
}
|
|
$rowData[] = $value;
|
|
}
|
|
|
|
// Linha de cabeçalho (1-indexed no PhpSpreadsheet)
|
|
if ($rowIndex === $headerRow + 1) {
|
|
$headers = $rowData;
|
|
continue;
|
|
}
|
|
|
|
// Pular linhas antes dos dados
|
|
if ($rowIndex < $dataStartRow + 1) {
|
|
continue;
|
|
}
|
|
|
|
// Verificar se a linha não está completamente vazia
|
|
$nonEmpty = array_filter($rowData, fn($v) => $v !== null && $v !== '');
|
|
if (!empty($nonEmpty)) {
|
|
$data[] = $rowData;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'headers' => $headers,
|
|
'data' => $data,
|
|
'total_rows' => count($data),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get headers from the Excel file
|
|
*/
|
|
public function getHeaders(string $filePath, array $options = []): array
|
|
{
|
|
$headerRow = $options['header_row'] ?? 0;
|
|
|
|
$spreadsheet = IOFactory::load($filePath);
|
|
$worksheet = $spreadsheet->getActiveSheet();
|
|
|
|
$headers = [];
|
|
$row = $worksheet->getRowIterator($headerRow + 1, $headerRow + 1)->current();
|
|
|
|
if ($row) {
|
|
$cellIterator = $row->getCellIterator();
|
|
$cellIterator->setIterateOnlyExistingCells(false);
|
|
|
|
foreach ($cellIterator as $cell) {
|
|
$headers[] = $cell->getCalculatedValue();
|
|
}
|
|
}
|
|
|
|
// Remover valores nulos do final
|
|
while (!empty($headers) && (end($headers) === null || end($headers) === '')) {
|
|
array_pop($headers);
|
|
}
|
|
|
|
return $headers;
|
|
}
|
|
|
|
/**
|
|
* Get preview data (first N rows)
|
|
*/
|
|
public function getPreview(string $filePath, int $rows = 10, array $options = []): array
|
|
{
|
|
$spreadsheet = IOFactory::load($filePath);
|
|
$worksheet = $spreadsheet->getActiveSheet();
|
|
|
|
$preview = [];
|
|
$rowCount = 0;
|
|
|
|
foreach ($worksheet->getRowIterator() as $row) {
|
|
if ($rowCount >= $rows) {
|
|
break;
|
|
}
|
|
|
|
$rowData = [];
|
|
$cellIterator = $row->getCellIterator();
|
|
$cellIterator->setIterateOnlyExistingCells(false);
|
|
|
|
foreach ($cellIterator as $cell) {
|
|
$value = $cell->getCalculatedValue();
|
|
// Tratar valores de data do Excel
|
|
if (\PhpOffice\PhpSpreadsheet\Shared\Date::isDateTime($cell)) {
|
|
try {
|
|
$dateValue = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
|
|
$value = $dateValue->format('d/m/Y');
|
|
} catch (\Exception $e) {
|
|
// Manter valor original
|
|
}
|
|
}
|
|
$rowData[] = $value;
|
|
}
|
|
|
|
// Remover valores nulos do final
|
|
while (!empty($rowData) && (end($rowData) === null || end($rowData) === '')) {
|
|
array_pop($rowData);
|
|
}
|
|
|
|
$preview[] = [
|
|
'row_index' => $rowCount,
|
|
'data' => $rowData,
|
|
];
|
|
|
|
$rowCount++;
|
|
}
|
|
|
|
// Contar total de linhas
|
|
$totalRows = $worksheet->getHighestRow();
|
|
|
|
return [
|
|
'preview' => $preview,
|
|
'total_rows' => $totalRows,
|
|
'columns_count' => !empty($preview) ? count($preview[0]['data']) : 0,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Check if parser supports the extension
|
|
*/
|
|
public static function supports(string $extension): bool
|
|
{
|
|
return in_array(strtolower($extension), self::$supportedExtensions);
|
|
}
|
|
}
|