Problème d'import de fichier xls sur mon module

Bonjour, je suis un débutant, j’ai créé un module sur dolibarr et j’essaie d’importer un fichier xls pour utiliser et manipuler les données qu’il contient. Cependant, l’import ne marche pas et ça me génère une erreur sur l’argument d’une fonction foreach de mon code. Erreur:
Action is import… File upload to c:/dolibarr/dolibarr_documents/chacornas/tmp/ fullname=c:/dolibarr/dolibarr_documents/chacornas/tmp/import.xls Extract data from c:/dolibarr/dolibarr_documents/chacornas/tmp/import.xls Extract data from sheet number
Warning : Invalid argument supplied for foreach() in C:\dolibarr\www\dolibarr\htdocs\custom\chacornas\base_import.php on line 199

Y’aurait-il quelqu’un qui pourrait me débloquer s’il vous plaît?

bonjour,
Peut-être nous donner la ligne qui pose problème.

Bonjour, oui biensûr :
foreach ($tab[$startProductsData] as $key => $val) {
if ($val != ‹  ›) {
$header[$key] = slugify($val);
}
}
Le problème viendrait apparemment de la première ligne d’après l’erreur affiché.
Merci

Bonjour,

L’erreur est claire, $tab[$startProductsData] n’est pas un array
Mais, on ne pourra pas faire plus si vous ne partagez pas le code.

Je vous mets le code en entier:

<?php
/* Copyright (C) 2017 Laurent Destailleur  <[email protected]>
 * Copyright (C) 2023 Eric Seigne <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

/**
 *   	\file       base_card.php
 *		\ingroup    chacornas
 *		\brief      Page to create/edit/view base
 */

//if (! defined('NOREQUIREDB'))              define('NOREQUIREDB', '1');				// Do not create database handler $db
//if (! defined('NOREQUIREUSER'))            define('NOREQUIREUSER', '1');				// Do not load object $user
//if (! defined('NOREQUIRESOC'))             define('NOREQUIRESOC', '1');				// Do not load object $mysoc
//if (! defined('NOREQUIRETRAN'))            define('NOREQUIRETRAN', '1');				// Do not load object $langs
//if (! defined('NOSCANGETFORINJECTION'))    define('NOSCANGETFORINJECTION', '1');		// Do not check injection attack on GET parameters
//if (! defined('NOSCANPOSTFORINJECTION'))   define('NOSCANPOSTFORINJECTION', '1');		// Do not check injection attack on POST parameters
//if (! defined('NOCSRFCHECK'))              define('NOCSRFCHECK', '1');				// Do not check CSRF attack (test on referer + on token).
//if (! defined('NOTOKENRENEWAL'))           define('NOTOKENRENEWAL', '1');				// Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on)
//if (! defined('NOSTYLECHECK'))             define('NOSTYLECHECK', '1');				// Do not check style html tag into posted data
//if (! defined('NOREQUIREMENU'))            define('NOREQUIREMENU', '1');				// If there is no need to load and show top and left menu
//if (! defined('NOREQUIREHTML'))            define('NOREQUIREHTML', '1');				// If we don't need to load the html.form.class.php
//if (! defined('NOREQUIREAJAX'))            define('NOREQUIREAJAX', '1');       	  	// Do not load ajax.lib.php library
//if (! defined("NOLOGIN"))                  define("NOLOGIN", '1');					// If this page is public (can be called outside logged session). This include the NOIPCHECK too.
//if (! defined('NOIPCHECK'))                define('NOIPCHECK', '1');					// Do not check IP defined into conf $dolibarr_main_restrict_ip
//if (! defined("MAIN_LANG_DEFAULT"))        define('MAIN_LANG_DEFAULT', 'auto');					// Force lang to a particular value
//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule');	// Force authentication handler
//if (! defined("NOREDIRECTBYMAINTOLOGIN"))  define('NOREDIRECTBYMAINTOLOGIN', 1);		// The main.inc.php does not make a redirect if not logged, instead show simple error message
//if (! defined("FORCECSP"))                 define('FORCECSP', 'none');				// Disable all Content Security Policies
//if (! defined('CSRFCHECK_WITH_TOKEN'))     define('CSRFCHECK_WITH_TOKEN', '1');		// Force use of CSRF protection with tokens even for GET
//if (! defined('NOBROWSERNOTIF'))     		 define('NOBROWSERNOTIF', '1');				// Disable browser notification
//if (! defined('NOSESSION'))     		     define('NOSESSION', '1');				    // Disable session

// Load Dolibarr environment
$res = 0;
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
    $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
    $i--;
    $j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
    $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
    $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
// Try main.inc.php using relative path
if (!$res && file_exists("../main.inc.php")) {
    $res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
    $res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
    $res = @include "../../../main.inc.php";
}
if (!$res) {
    die("Include of main fails");
}

require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
dol_include_once('/chacornas/class/base.class.php');
dol_include_once('/chacornas/lib/chacornas_base.lib.php');
dol_include_once('/chacornas/lib/chacornas.lib.php');
require 'vendor/autoload.php';
//print "fillData with " . json_encode($array) . "\n";

use Shuchkin\SimpleXLSX;

// Load translation files required by the page
$langs->loadLangs(array("chacornas@chacornas", "other"));

// Get parameters
$id = GETPOST('id', 'int');
$ref = GETPOST('ref', 'alpha');
$lineid   = GETPOST('lineid', 'int');

$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
$cancel = GETPOST('cancel', 'aZ09');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
$backtopage = GETPOST('backtopage', 'alpha');
$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09');

// Initialize technical objects
$object = new Base($db);
$extrafields = new ExtraFields($db);
$diroutputmassaction = $conf->chacornas->dir_output.'/temp/massgeneration/'.$user->id;
$hookmanager->initHooks(array('basecard', 'globalcard')); // Note that conf->hooks_modules contains array

// Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);

$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');

// Initialize array of search criterias
$search_all = GETPOST("search_all", 'alpha');
$search = array();
foreach ($object->fields as $key => $val) {
    if (GETPOST('search_'.$key, 'alpha')) {
        $search[$key] = GETPOST('search_'.$key, 'alpha');
    }
}

if (empty($action) && empty($id) && empty($ref)) {
    $action = 'view';
}

// Load object
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once.

// There is several ways to check permission.
// Set $enablepermissioncheck to 1 to enable a minimum low level of checks
$enablepermissioncheck = 0;
if ($enablepermissioncheck) {
    $permissiontoread = $user->rights->chacornas->base->read;
    $permissiontoadd = $user->rights->chacornas->base->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
    $permissiontodelete = $user->rights->chacornas->base->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
    $permissionnote = $user->rights->chacornas->base->write; // Used by the include of actions_setnotes.inc.php
    $permissiondellink = $user->rights->chacornas->base->write; // Used by the include of actions_dellink.inc.php
} else {
    $permissiontoread = 1;
    $permissiontoadd = 1; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
    $permissiontodelete = 1;
    $permissionnote = 1;
    $permissiondellink = 1;
}

$upload_dir = $conf->chacornas->multidir_output[isset($object->entity) ? $object->entity : 1].'/base';

// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (isset($object->status) && ($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (empty($conf->chacornas->enabled)) {
    accessforbidden();
}
if (!$permissiontoread) {
    accessforbidden();
}


/*
 * Actions
 */

$debug = false;           //active le mode debug
$sheetName = "Export_Base"; //le nom de la feuille dont on veut extraire les données
$startGenData = 0; //numéro de la ligne à laquelle se trouvent les données générales (ligne 1&2 à priori)
$startProductsData = 10; //numéro de la ligne à laquelle les produits commencent
$worksheetIndex = -1;

$action = GETPOST('action', 'aZ09');
if ($action == 'import') {
    print "Action is $action...\n";
    if (!empty($_FILES['fileToUpload'])) {
        // print "File upload...\n";
		//print json_encode($_FILES['fileToUpload']);
        $dirupload = DOL_DATA_ROOT.'/chacornas/tmp/';
        $completefilename = $dirupload . "import.xls";
        if (!is_dir($dirupload)) {
            dol_mkdir($dirupload);
        }
		print "File upload to $dirupload fullname=$completefilename\n";
        if (dol_move_uploaded_file($_FILES['fileToUpload']['tmp_name'], $completefilename, 1)) {
            print "Extract data from $completefilename\n";

            $xlsx = SimpleXLSX::parseFile($completefilename, $debug);
            $sheets = $xlsx->sheetNames();
            $sheetIndex = array_search($sheetName, $sheets);

            print "Extract data from sheet number $sheetIndex\n";
            $tab = $xlsx->rows($sheetIndex, 0);

            //recuperation des etiquettes de colonnes
            $header = array();
            foreach ($tab[$startProductsData] as $key => $val) {
                if ($val != '') {
                    $header[$key] = slugify($val);
                }
            }

            //puis des données
            for ($i = $startProductsData+1; $i < count($tab) && $i < 200; $i++) {
				$nbval = 0;
                $product = array();
                foreach ($tab[$i] as $key => $val) {
                    $headerKey = $header[$key];
                    if (trim($val) != '') {
                        $product[$headerKey] = trim($val);
						$nbval++;
                    }
                }

                //Creation de l'entrée dans la base dolibarr uniquement si la ligne n'est pas vide
                if ($nbval > 0) {
					print "nbval pour ligne $i : $nbval <br />\n";
                    $base = new Base($db);
                    $base->fillData($product);
                    $base->create($user);
                }
            }
        }else {
			print "erreur pour dol_move...";
		}
    }
}

/*
 * View
 *
 * Put here all code to build page
 */

$form = new Form($db);
$formfile = new FormFile($db);
$formproject = new FormProjets($db);

$title = $langs->trans("Base");
$help_url = '';
llxHeader('', $title, $help_url);

print "<h1>Import de fichier XLS</h1>";

print '<form method="POST" enctype="multipart/form-data" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="import">';
print '<input type="file" id="myFile" name="fileToUpload">';

print $form->buttonsSaveCancel("Import");

// Example : Adding jquery code
// print '<script type="text/javascript">
// jQuery(document).ready(function() {
// 	function init_myfunc()
// 	{
// 		jQuery("#myid").removeAttr(\'disabled\');
// 		jQuery("#myid").attr(\'disabled\',\'disabled\');
// 	}
// 	init_myfunc();
// 	jQuery("#mybutton").click(function() {
// 		init_myfunc();
// 	});
// });
// </script>';


// End of page
llxFooter();
$db->close();

?>

Bonjour,

N’est pas défini

Si à la ligne 172 : $startProductsData = 10; //numéro de la ligne à laquelle les produits commencent

Donc

$tab[$startProductsData]

N’est pas un Array

Si car sur la ligne 195: $tab = $xlsx->rows($sheetIndex, 0);
$tab contiendra un tableau ou une structure de données contenant les lignes de données extraites du fichier Excel.

Donc dites à PHP qu’il se trompe :crazy_face:

Donc y’a pas d’erreurs?

C’était un trait d’humour, forcément qu’il y a une erreur, PHP ne se trompe pas.

Mais, comme vous semblez avoir réponse à tout !

Bonjour,

Rajoutez cette ligne juste avant le foreach de la ligne 199, et vous verrez bien si vous avez un array ou pas.


var_dump($tab[$startProductsData]); die;

C’est pas question de j’ai réponse à tout, rien à voir, je ne serais pas ici sinon!
C’est juste que vous me faites des suggestions sur lesquelles il n’y a a priori pas d’erreurs.

Bonjour,
Merci pour votre réponse. J’ai rajouté la ligne et maintenant j’ai ça comme erreur: Action is import… File upload to c:/dolibarr/dolibarr_documents/chacornas/tmp/ fullname=c:/dolibarr/dolibarr_documents/chacornas/tmp/import.xls Extract data from c:/dolibarr/dolibarr_documents/chacornas/tmp/import.xls Extract data from sheet number NULL

ce n’est pas un message d’erreur c’est ce que renvoie votre code avec les lignes print et ensuite le var_dump que vous avez ajouté

Analysez ce résultat et vous verrez bien qu’il y a des problèmes. Vous avez $sheetIndex qui est vide puisque derrière sheet number il n’y a rien.

Enfin ça dépasse le cadre de Dolibarr ici, il faut commencer par apprendre le langage PHP.

2 « J'aime »