7 votes

Laravel excel maatwebsite 3.1 import, la colonne date dans la cellule excel revient comme un nombre de format inconnu. Comment résoudre ce problème ?

En utilisant Maatwebsite/Laravel-Excel version 3.1 pour importer une feuille Excel, j'ai été confronté à un problème : la colonne date-heure de la feuille Excel renvoie un nombre inconnu. Comment résoudre ce problème ? Exemple : Considérons la valeur de la cellule "29/07/1989" qui renvoie "32178" lors de l'importation.

22voto

Qraxin Points 423

Les chiffres proviennent d'Excel lui-même, les dates sont stockées dans Excel sous forme numérique. numériques. http://www.cpearson.com/excel/datetime.htm

Pour le framework Laravel 5.6 et le package maatwebsite/excel version 3.1, pour convertir la date des chiffres excel au format normal de date, cette fonction PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($dateFromExcel) peut être utilisé. Il accepte un entier (excel date) et retourne un objet DateTime objet.

Vous trouverez de plus amples informations ici https://github.com/Maatwebsite/Laravel-Excel/issues/1832

De cette réponse : https://stackoverflow.com/a/55139981/9133724

14voto

Reno Anthus Points 325

Résolu ! Voici le code que j'ai utilisé pour résoudre mon problème :

Carbon\Carbon::instance(\PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value));

4voto

J'ai essayé la solution ci-dessus mais je suis toujours bloqué avec erreur de valeur non numérique

J'ai réussi à résoudre ce problème en utilisant


$date = intval($row['value]);

\PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($date)->format('d/m/Y')

0voto

Ce "nombre inconnu" est un timestamp excel, de cette façon il stocke les données de date et d'heure en interne.

par exemple :

123213.0: it's just a date
213233.1233: is a date and time
0.1233: it's one hour

Si vous pouvez mapper la cellule et que vous savez quelle colonne aura toujours une date / heure / date-heure, vous pouvez utiliser des cellules mappées ou les convertir manuellement, voir : https://stackoverflow.com/a/59049044

Sinon, si votre besoin implique la résolution dynamique des champs de type datetime, j'ai écrit une méthode qui se charge de détecter automatiquement si la valeur est une datetime de manière dynamique (que vous sachiez ou non s'il y aura une datetime dans cette colonne) ou j'ai essayé différents types de données et cela fonctionne bien.

   /**
 * @param Cell $cell
 * @param $value
 * 
 * @return boolean;
 */
public function bindValue(Cell $cell, $value)
{
    $formatedCellValue = $this->formatDateTimeCell($value, $datetime_output_format = "d-m-Y H:i:s", $date_output_format = "d-m-Y", $time_output_format = "H:i:s" );
    if($formatedCellValue != false){
        $cell->setValueExplicit($formatedCellValue, DataType::TYPE_STRING);
        return true;
    }

    // else return default behavior
    return parent::bindValue($cell, $value);
}

/**
 * 
 * Convert excel-timestamp to Php-timestamp and again to excel-timestamp to compare both compare
 * By Leonardo J. Jauregui ( @Nanod10 | siskit dot com )
 * 
 * @param $value (cell value)
 * @param String $datetime_output_format
 * @param String $date_output_format
 * @param String $time_output_format
 * 
 * @return $formatedCellValue
 */
private function formatDateTimeCell( $value, $datetime_output_format = "Y-m-d H:i:s", $date_output_format = "Y-m-d", $time_output_format = "H:i:s" )
{

    // is only time flag
    $is_only_time = false;

    // Divide Excel-timestamp to know if is Only Date, Only Time or both of them
    $excel_datetime_exploded = explode(".", $value);

    // if has dot, maybe date has time or is only time
    if(strstr($value,".")){
        // Excel-timestamp to Php-DateTimeObject
        $dateTimeObject = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
        // if Excel-timestamp > 0 then has Date and Time 
        if(intval($excel_datetime_exploded[0]) > 0){
            // Date and Time
            $output_format = $datetime_output_format;
            $is_only_time = false;
        }else{
            // Only time
            $output_format = $time_output_format;
            $is_only_time = true;
        }
    }else{
        // Only Date
        // Excel-timestamp to Php-DateTimeObject
        $dateTimeObject = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
        $output_format = $date_output_format;
        $is_only_time = false;
    }

    // Php-DateTimeObject to Php-timestamp
    $phpTimestamp = $dateTimeObject->getTimestamp();

    // Php-timestamp to Excel-timestamp
    $excelTimestamp = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $phpTimestamp );

    // if is only Time
    if($is_only_time){
        // 01-01-1970 = 25569
        // Substract to match PhpToExcel conversion
        $excelTimestamp = $excelTimestamp - 25569;
    }

    /* 
    // uncoment to debug manualy and see if working
    $debug_arr = [
            "value"=>$value,
            "value_float"=>floatval($value),
            "dateTimeObject"=>$dateTimeObject,
            "phpTimestamp"=>$phpTimestamp,
            "excelTimestamp"=>$excelTimestamp,
            "default_date_format"=>$dateTimeObject->format('Y-m-d H:i:s'),
            "custom_date_format"=>$dateTimeObject->format($output_format)
        ];

    if($cell->getColumn()=="Q"){
        if($cell->getRow()=="2"){
            if(floatval($value)===$excelTimestamp){
                dd($debug_arr);
            }
        }
    }

    */

    // if the values match
    if( floatval($value) === $excelTimestamp ){
        // is a fucking date! ;)
        $formatedCellValue = $dateTimeObject->format($output_format);
        return $formatedCellValue;
    }else{
        // return normal value
        return false;
    }

}

0voto

Pathros Points 2418

Sur la base de Skyrem Brilliant Grâce à la réponse brillante de @skyrem, j'ai résolu le problème de cette façon :

<?php

//...

class YourExcelImport implements OnEachRow, WithValidation, WithHeadingRow
{
   // ...

    /**
     * Tweak the data slightly before sending it to the validator
     * @param $data
     * @param $index
     * @return mixed
     */
    public function prepareForValidation($data, $index)
    {
        //Fix that Excel's numeric date (counting in days since 1900-01-01)
        $data['your_date_column'] = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($data['your_date_column'])->format('Y-m-d');
        //...
    }

    /**
     * List the validation rules
     * @return array
     */
    public function rules(): array
    {
        return [
            'your_date_column'=>'required|date_format:Y-m-d',
            //..
        ];
    }
}
?>

Cela a fait l'affaire et la validation passe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X