1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* Copyright (C) 2006-2015 Laurent Destailleur <[email protected]> |
4
|
|
|
* Copyright (C) 2012 Marcos García <[email protected]> |
5
|
|
|
* Copyright (C) 2024 William Mead <[email protected]> |
6
|
|
|
* Copyright (C) 2024 Frédéric France <[email protected]> |
7
|
|
|
* Copyright (C) 2024 Rafael San José <[email protected]> |
8
|
|
|
* |
9
|
|
|
* This program is free software; you can redistribute it and/or modify |
10
|
|
|
* it under the terms of the GNU General Public License as published by |
11
|
|
|
* the Free Software Foundation; either version 3 of the License, or |
12
|
|
|
* (at your option) any later version. |
13
|
|
|
* |
14
|
|
|
* This program is distributed in the hope that it will be useful, |
15
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
16
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17
|
|
|
* GNU General Public License for more details. |
18
|
|
|
* |
19
|
|
|
* You should have received a copy of the GNU General Public License |
20
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
21
|
|
|
*/ |
22
|
|
|
|
23
|
|
|
use Dolibarr\Code\Core\Classes\Translate; |
24
|
|
|
use Dolibarr\Code\Exports\Classes\ModeleExports; |
25
|
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
26
|
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; |
27
|
|
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; |
28
|
|
|
use Dolibarr\Lib\ViewMain; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* \file htdocs/core/modules/export/export_excel2007.modules.php |
32
|
|
|
* \ingroup export |
33
|
|
|
* \brief File of class to generate export file with Excel format |
34
|
|
|
*/ |
35
|
|
|
|
36
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php'; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Class to build export files with Excel format |
40
|
|
|
*/ |
41
|
|
|
class ExportExcel2007 extends ModeleExports |
42
|
|
|
{ |
43
|
|
|
/** |
44
|
|
|
* @var string ID |
45
|
|
|
*/ |
46
|
|
|
public $id; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var string Export Excel label |
50
|
|
|
*/ |
51
|
|
|
public $label; |
52
|
|
|
|
53
|
|
|
public $extension; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Dolibarr version of the loaded document |
57
|
|
|
* @var string |
58
|
|
|
*/ |
59
|
|
|
public $version = 'dolibarr'; |
60
|
|
|
|
61
|
|
|
public $label_lib; |
62
|
|
|
|
63
|
|
|
public $version_lib; |
64
|
|
|
|
65
|
|
|
/** @var Spreadsheet */ |
66
|
|
|
public $workbook; // Handle file |
67
|
|
|
|
68
|
|
|
public $worksheet; // Handle sheet |
69
|
|
|
|
70
|
|
|
public $styleArray; |
71
|
|
|
|
72
|
|
|
public $row; |
73
|
|
|
|
74
|
|
|
public $col; |
75
|
|
|
|
76
|
|
|
public $file; // To save filename |
77
|
|
|
|
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Constructor |
81
|
|
|
* |
82
|
|
|
* @param DoliDB $db Database handler |
83
|
|
|
*/ |
84
|
|
|
public function __construct($db) |
85
|
|
|
{ |
86
|
|
|
global $langs; |
87
|
|
|
$this->db = $db; |
88
|
|
|
|
89
|
|
|
$this->id = 'excel2007'; // Same value then xxx in file name export_xxx.modules.php |
90
|
|
|
$this->label = 'Excel 2007'; // Label of driver |
91
|
|
|
$this->desc = $langs->trans('Excel2007FormatDesc'); |
92
|
|
|
$this->extension = 'xlsx'; // Extension for generated file by this driver |
93
|
|
|
$this->picto = 'mime/xls'; // Picto |
94
|
|
|
$this->version = '1.30'; // Driver version |
95
|
|
|
$this->phpmin = array(7, 0); // Minimum version of PHP required by module |
96
|
|
|
|
97
|
|
|
$this->disabled = 0; |
98
|
|
|
|
99
|
|
|
if (empty($this->disabled)) { |
100
|
|
|
require_once PHPEXCELNEW_PATH . 'Spreadsheet.php'; |
101
|
|
|
$this->label_lib = 'PhpSpreadSheet'; |
102
|
|
|
$this->version_lib = '1.12.0'; // No way to get info from library |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
$this->row = 0; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* getDriverId |
110
|
|
|
* |
111
|
|
|
* @return string |
112
|
|
|
*/ |
113
|
|
|
public function getDriverId() |
114
|
|
|
{ |
115
|
|
|
return $this->id; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* getDriverLabel |
120
|
|
|
* |
121
|
|
|
* @return string Return driver label |
122
|
|
|
*/ |
123
|
|
|
public function getDriverLabel() |
124
|
|
|
{ |
125
|
|
|
return $this->label; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* getDriverLabel |
130
|
|
|
* |
131
|
|
|
* @return string Return driver label |
132
|
|
|
*/ |
133
|
|
|
public function getDriverLabelBis() |
134
|
|
|
{ |
135
|
|
|
global $langs; |
136
|
|
|
$langs->load("errors"); |
137
|
|
|
return $langs->trans("NumberOfLinesLimited"); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* getDriverDesc |
142
|
|
|
* |
143
|
|
|
* @return string |
144
|
|
|
*/ |
145
|
|
|
public function getDriverDesc() |
146
|
|
|
{ |
147
|
|
|
return $this->desc; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* getDriverExtension |
152
|
|
|
* |
153
|
|
|
* @return string |
154
|
|
|
*/ |
155
|
|
|
public function getDriverExtension() |
156
|
|
|
{ |
157
|
|
|
return $this->extension; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* getDriverVersion |
162
|
|
|
* |
163
|
|
|
* @return string |
164
|
|
|
*/ |
165
|
|
|
public function getDriverVersion() |
166
|
|
|
{ |
167
|
|
|
return $this->version; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* getLibLabel |
172
|
|
|
* |
173
|
|
|
* @return string |
174
|
|
|
*/ |
175
|
|
|
public function getLibLabel() |
176
|
|
|
{ |
177
|
|
|
return $this->label_lib; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* getLibVersion |
182
|
|
|
* |
183
|
|
|
* @return string |
184
|
|
|
*/ |
185
|
|
|
public function getLibVersion() |
186
|
|
|
{ |
187
|
|
|
return $this->version_lib; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
|
191
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Open output file |
195
|
|
|
* |
196
|
|
|
* @param string $file File name to generate |
197
|
|
|
* @param Translate $outputlangs Output language object |
198
|
|
|
* @return int Return integer <0 if KO, >=0 if OK |
199
|
|
|
*/ |
200
|
|
|
public function open_file($file, $outputlangs) |
201
|
|
|
{ |
202
|
|
|
// phpcs:enable |
203
|
|
|
global $user, $langs; |
204
|
|
|
|
205
|
|
|
dol_syslog(get_only_class($this) . "::open_file file=" . $file); |
206
|
|
|
$this->file = $file; |
207
|
|
|
|
208
|
|
|
$ret = 1; |
209
|
|
|
|
210
|
|
|
$outputlangs->load("exports"); |
211
|
|
|
|
212
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/includes/phpoffice/phpspreadsheet/src/autoloader.php'; |
213
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/includes/Psr/autoloader.php'; |
214
|
|
|
require_once PHPEXCELNEW_PATH . 'Spreadsheet.php'; |
215
|
|
|
|
216
|
|
|
if ($this->id == 'excel2007') { |
217
|
|
|
if (!class_exists('ZipArchive')) { // For Excel2007, PHPSpreadSheet may need ZipArchive |
218
|
|
|
$langs->load("errors"); |
219
|
|
|
$this->error = $langs->trans('ErrorPHPNeedModule', 'zip'); |
220
|
|
|
return -1; |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
$this->workbook = new Spreadsheet(); |
225
|
|
|
$this->workbook->getProperties()->setCreator($user->getFullName($outputlangs) . ' - ' . DOL_APPLICATION_TITLE . ' ' . DOL_VERSION); |
226
|
|
|
//$this->workbook->getProperties()->setLastModifiedBy('Dolibarr '.DOL_VERSION); |
227
|
|
|
$this->workbook->getProperties()->setTitle(basename($file)); |
228
|
|
|
$this->workbook->getProperties()->setSubject(basename($file)); |
229
|
|
|
$this->workbook->getProperties()->setDescription(DOL_APPLICATION_TITLE . ' ' . DOL_VERSION); |
230
|
|
|
|
231
|
|
|
$this->workbook->setActiveSheetIndex(0); |
232
|
|
|
$this->workbook->getActiveSheet()->setTitle($outputlangs->trans("Sheet")); |
233
|
|
|
$this->workbook->getActiveSheet()->getDefaultRowDimension()->setRowHeight(16); |
234
|
|
|
|
235
|
|
|
return $ret; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Write header |
242
|
|
|
* |
243
|
|
|
* @param Translate $outputlangs Object lang to translate values |
244
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
245
|
|
|
*/ |
246
|
|
|
public function write_header($outputlangs) |
247
|
|
|
{ |
248
|
|
|
// phpcs:enable |
249
|
|
|
//$outputlangs->charset_output='ISO-8859-1'; // Because Excel 5 format is ISO |
250
|
|
|
|
251
|
|
|
return 0; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
|
255
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Output title line into file |
259
|
|
|
* |
260
|
|
|
* @param array $array_export_fields_label Array with list of label of fields |
261
|
|
|
* @param array $array_selected_sorted Array with list of field to export |
262
|
|
|
* @param Translate $outputlangs Object lang to translate values |
263
|
|
|
* @param array $array_types Array with types of fields |
264
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
265
|
|
|
*/ |
266
|
|
|
public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) |
267
|
|
|
{ |
268
|
|
|
// phpcs:enable |
269
|
|
|
|
270
|
|
|
// Create a format for the column headings |
271
|
|
|
$this->workbook->getActiveSheet()->getStyle('1')->getFont()->setBold(true); |
272
|
|
|
$this->workbook->getActiveSheet()->getStyle('1')->getAlignment()->setHorizontal(PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT); |
273
|
|
|
$selectlabel = array(); |
274
|
|
|
|
275
|
|
|
$this->col = 1; |
276
|
|
|
|
277
|
|
|
foreach ($array_selected_sorted as $code => $value) { |
278
|
|
|
$alias = $array_export_fields_label[$code]; |
279
|
|
|
//print "dd".$alias; |
280
|
|
|
if (empty($alias)) { |
281
|
|
|
dol_print_error(null, 'Bad value for field with code=' . $code . '. Try to redefine export.'); |
282
|
|
|
} |
283
|
|
|
$typefield = isset($array_types[$code]) ? $array_types[$code] : ''; |
284
|
|
|
|
285
|
|
|
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { |
286
|
|
|
$selectlabel[$code . "_label"] = $alias . "_label"; |
287
|
|
|
} |
288
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, $outputlangs->transnoentities($alias)); |
|
|
|
|
289
|
|
|
if (!empty($array_types[$code]) && in_array($array_types[$code], array('Date', 'Numeric', 'TextAuto'))) { // Set autowidth for some types |
290
|
|
|
$this->workbook->getActiveSheet()->getColumnDimension($this->column2Letter($this->col + 1))->setAutoSize(true); |
291
|
|
|
} |
292
|
|
|
$this->col++; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
// Complete with some columns to add columns with the labels of columns of type Select, so we have more then the ID |
296
|
|
|
foreach ($selectlabel as $key => $value) { |
297
|
|
|
$code = preg_replace('/_label$/', '', $key); |
298
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, $outputlangs->transnoentities($value)); |
299
|
|
|
if (!empty($array_types[$code]) && in_array($array_types[$code], array('Date', 'Numeric', 'TextAuto'))) { // Set autowidth for some types |
300
|
|
|
$this->workbook->getActiveSheet()->getColumnDimension($this->column2Letter($this->col + 1))->setAutoSize(true); |
301
|
|
|
} |
302
|
|
|
$this->col++; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
$this->row++; |
306
|
|
|
return 0; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Output record line into file |
313
|
|
|
* |
314
|
|
|
* @param array $array_selected_sorted Array with list of field to export |
315
|
|
|
* @param Resource $objp A record from a fetch with all fields from select |
316
|
|
|
* @param Translate $outputlangs Object lang to translate values |
317
|
|
|
* @param array $array_types Array with types of fields |
318
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
319
|
|
|
*/ |
320
|
|
|
public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) |
321
|
|
|
{ |
322
|
|
|
// phpcs:enable |
323
|
|
|
|
324
|
|
|
// Define first row |
325
|
|
|
$this->col = 1; |
326
|
|
|
|
327
|
|
|
$reg = array(); |
328
|
|
|
$selectlabelvalues = array(); |
329
|
|
|
foreach ($array_selected_sorted as $code => $value) { |
330
|
|
|
if (strpos($code, ' as ') == 0) { |
331
|
|
|
$alias = str_replace(array('.', '-', '(', ')'), '_', $code); |
332
|
|
|
} else { |
333
|
|
|
$alias = substr($code, strpos($code, ' as ') + 4); |
334
|
|
|
} |
335
|
|
|
if (empty($alias)) { |
336
|
|
|
dol_print_error(null, 'Bad value for field with code=' . $code . '. Try to redefine export.'); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
$newvalue = !empty($objp->$alias) ? $objp->$alias : ''; |
340
|
|
|
|
341
|
|
|
$newvalue = $this->excel_clean($newvalue); |
342
|
|
|
$typefield = isset($array_types[$code]) ? $array_types[$code] : ''; |
343
|
|
|
|
344
|
|
|
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { |
345
|
|
|
$array = jsonOrUnserialize($typefield); |
346
|
|
|
if (is_array($array) && !empty($newvalue)) { |
347
|
|
|
$array = $array['options']; |
348
|
|
|
$selectlabelvalues[$code . "_label"] = $array[$newvalue]; |
349
|
|
|
} else { |
350
|
|
|
$selectlabelvalues[$code . "_label"] = ""; |
351
|
|
|
} |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
// Traduction newvalue |
355
|
|
|
if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) { |
356
|
|
|
$newvalue = $outputlangs->transnoentities($reg[1]); |
357
|
|
|
} else { |
358
|
|
|
$newvalue = $outputlangs->convToOutputCharset($newvalue); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
if (preg_match('/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/i', $newvalue)) { |
362
|
|
|
$newvalue = dol_stringtotime($newvalue); |
363
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($newvalue)); |
364
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
|
|
|
|
365
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('yyyy-mm-dd'); |
366
|
|
|
} elseif (preg_match('/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/i', $newvalue)) { |
367
|
|
|
$newvalue = dol_stringtotime($newvalue); |
368
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($newvalue)); |
369
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
370
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('yyyy-mm-dd h:mm:ss'); |
371
|
|
|
} else { |
372
|
|
|
if ($typefield == 'Text' || $typefield == 'TextAuto') { |
373
|
|
|
// If $newvalue start with an equal sign we don't want it to be interpreted as a formula, so we add a '. Such transformation should be |
374
|
|
|
// done by SetCellValueByColumnAndRow but it is not, so we do it ourself. |
375
|
|
|
$newvalue = (dol_substr($newvalue, 0, 1) === '=' ? '\'' : '') . $newvalue; |
376
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, $newvalue); |
377
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
378
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('@'); |
379
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getAlignment()->setHorizontal(PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT); |
380
|
|
|
} else { |
381
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, $newvalue); |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
$this->col++; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
// Complete with some columns to add columns with the labels of columns of type Select, so we have more then the ID |
388
|
|
|
foreach ($selectlabelvalues as $key => $newvalue) { |
389
|
|
|
$code = preg_replace('/_label$/', '', $key); |
390
|
|
|
$typefield = isset($array_types[$code]) ? $array_types[$code] : ''; |
391
|
|
|
|
392
|
|
|
if (preg_match('/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/i', $newvalue)) { |
393
|
|
|
$newvalue = dol_stringtotime($newvalue); |
394
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($newvalue)); |
395
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
396
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('yyyy-mm-dd'); |
397
|
|
|
} elseif (preg_match('/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/i', $newvalue)) { |
398
|
|
|
$newvalue = dol_stringtotime($newvalue); |
399
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($newvalue)); |
400
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
401
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('yyyy-mm-dd h:mm:ss'); |
402
|
|
|
} else { |
403
|
|
|
if ($typefield == 'Text' || $typefield == 'TextAuto') { |
404
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, (string)$newvalue); |
405
|
|
|
$coord = $this->workbook->getActiveSheet()->getCellByColumnAndRow($this->col, $this->row + 1)->getCoordinate(); |
406
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getNumberFormat()->setFormatCode('@'); |
407
|
|
|
$this->workbook->getActiveSheet()->getStyle($coord)->getAlignment()->setHorizontal(PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT); |
408
|
|
|
} else { |
409
|
|
|
$this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($this->col, $this->row + 1, $newvalue); |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
$this->col++; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
$this->row++; |
416
|
|
|
return 0; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
|
420
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Write footer |
424
|
|
|
* |
425
|
|
|
* @param Translate $outputlangs Output language object |
426
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
427
|
|
|
*/ |
428
|
|
|
public function write_footer($outputlangs) |
429
|
|
|
{ |
430
|
|
|
// phpcs:enable |
431
|
|
|
return 0; |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
|
435
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* Close Excel file |
439
|
|
|
* |
440
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
441
|
|
|
*/ |
442
|
|
|
public function close_file() |
443
|
|
|
{ |
444
|
|
|
// phpcs:enable |
445
|
|
|
|
446
|
|
|
$objWriter = new Xlsx($this->workbook); |
447
|
|
|
$objWriter->save($this->file); |
448
|
|
|
$this->workbook->disconnectWorksheets(); |
449
|
|
|
unset($this->workbook); |
450
|
|
|
|
451
|
|
|
return 1; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
|
455
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* Clean a cell to respect rules of Excel file cells |
459
|
|
|
* |
460
|
|
|
* @param string $newvalue String to clean |
461
|
|
|
* @return string Value cleaned |
462
|
|
|
*/ |
463
|
|
|
public function excel_clean($newvalue) |
464
|
|
|
{ |
465
|
|
|
// phpcs:enable |
466
|
|
|
// Rule Dolibarr: No HTML |
467
|
|
|
$newvalue = dol_string_nohtmltag($newvalue); |
468
|
|
|
|
469
|
|
|
return $newvalue; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
|
473
|
|
|
/** |
474
|
|
|
* Convert a column to letter (1->A, 0->B, 27->AA, ...) |
475
|
|
|
* |
476
|
|
|
* @param int $c Column position |
477
|
|
|
* @return string Letter |
478
|
|
|
*/ |
479
|
|
|
public function column2Letter($c) |
480
|
|
|
{ |
481
|
|
|
$c = intval($c); |
482
|
|
|
if ($c <= 0) { |
483
|
|
|
return ''; |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
$letter = ''; |
487
|
|
|
while ($c != 0) { |
488
|
|
|
$p = ($c - 1) % 26; |
489
|
|
|
$c = intval(($c - $p) / 26); |
490
|
|
|
$letter = chr(65 + $p) . $letter; |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
return $letter; |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
/** |
497
|
|
|
* Set cell value and automatically merge if we give an endcell |
498
|
|
|
* |
499
|
|
|
* @param string $val cell value |
500
|
|
|
* @param string $startCell starting cell |
501
|
|
|
* @param string $endCell ending cell |
502
|
|
|
* @return int 1 if success -1 if failed |
503
|
|
|
*/ |
504
|
|
|
public function setCellValue($val, $startCell, $endCell = '') |
505
|
|
|
{ |
506
|
|
|
try { |
507
|
|
|
$this->workbook->getActiveSheet()->setCellValue($startCell, $val); |
508
|
|
|
|
509
|
|
|
if (!empty($endCell)) { |
510
|
|
|
$cellRange = $startCell . ':' . $endCell; |
511
|
|
|
$this->workbook->getActiveSheet()->mergeCells($startCell . ':' . $endCell); |
512
|
|
|
} else { |
513
|
|
|
$cellRange = $startCell; |
514
|
|
|
} |
515
|
|
|
if (!empty($this->styleArray)) { |
516
|
|
|
$this->workbook->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styleArray); |
517
|
|
|
} |
518
|
|
|
} catch (Exception $e) { |
519
|
|
|
$this->error = $e->getMessage(); |
520
|
|
|
return -1; |
521
|
|
|
} |
522
|
|
|
return 1; |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
/** |
526
|
|
|
* Set border style |
527
|
|
|
* |
528
|
|
|
* @param string $thickness style \PhpOffice\PhpSpreadsheet\Style\Border |
529
|
|
|
* @param string $color color \PhpOffice\PhpSpreadsheet\Style\Color |
530
|
|
|
* @return int 1 if ok |
531
|
|
|
*/ |
532
|
|
|
public function setBorderStyle($thickness, $color) |
533
|
|
|
{ |
534
|
|
|
$this->styleArray['borders'] = array( |
535
|
|
|
'outline' => array( |
536
|
|
|
'borderStyle' => $thickness, |
537
|
|
|
'color' => array('argb' => $color) |
538
|
|
|
) |
539
|
|
|
); |
540
|
|
|
return 1; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* Set font style |
545
|
|
|
* |
546
|
|
|
* @param bool $bold true if bold |
547
|
|
|
* @param string $color color \PhpOffice\PhpSpreadsheet\Style\Color |
548
|
|
|
* @return int 1 |
549
|
|
|
*/ |
550
|
|
|
public function setFontStyle($bold, $color) |
551
|
|
|
{ |
552
|
|
|
$this->styleArray['font'] = array( |
553
|
|
|
'color' => array('argb' => $color), |
554
|
|
|
'bold' => $bold |
555
|
|
|
); |
556
|
|
|
return 1; |
557
|
|
|
} |
558
|
|
|
|
559
|
|
|
/** |
560
|
|
|
* Set alignment style (horizontal, left, right, ...) |
561
|
|
|
* |
562
|
|
|
* @param string $horizontal PhpOffice\PhpSpreadsheet\Style\Alignment |
563
|
|
|
* @return int 1 |
564
|
|
|
*/ |
565
|
|
|
public function setAlignmentStyle($horizontal) |
566
|
|
|
{ |
567
|
|
|
$this->styleArray['alignment'] = array('horizontal' => $horizontal); |
568
|
|
|
return 1; |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
/** |
572
|
|
|
* Reset Style |
573
|
|
|
* @return int 1 |
574
|
|
|
*/ |
575
|
|
|
public function resetStyle() |
576
|
|
|
{ |
577
|
|
|
$this->styleArray = array(); |
578
|
|
|
return 1; |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
/** |
582
|
|
|
* Make a NxN Block in sheet |
583
|
|
|
* |
584
|
|
|
* @param string $startCell starting cell |
585
|
|
|
* @param array $TDatas array(ColumnName=>array(Row value 1, row value 2, etc ...)) |
586
|
|
|
* @param bool $boldTitle true if bold headers |
587
|
|
|
* @return int 1 if OK, -1 if KO |
588
|
|
|
*/ |
589
|
|
|
public function setBlock($startCell, $TDatas = array(), $boldTitle = false) |
590
|
|
|
{ |
591
|
|
|
try { |
592
|
|
|
if (!empty($TDatas)) { |
593
|
|
|
$startCell = $this->workbook->getActiveSheet()->getCell($startCell); |
594
|
|
|
$startColumn = Coordinate::columnIndexFromString($startCell->getColumn()); |
595
|
|
|
$startRow = $startCell->getRow(); |
596
|
|
|
foreach ($TDatas as $column => $TRows) { |
597
|
|
|
if ($boldTitle) { |
598
|
|
|
$this->setFontStyle(true, $this->styleArray['font']['color']['argb']); |
599
|
|
|
} |
600
|
|
|
$cell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn, $startRow); |
601
|
|
|
$this->setCellValue($column, $cell->getCoordinate()); |
602
|
|
|
$rowPos = $startRow; |
603
|
|
|
if ($boldTitle) { |
604
|
|
|
$this->setFontStyle(false, $this->styleArray['font']['color']['argb']); |
605
|
|
|
} |
606
|
|
|
foreach ($TRows as $row) { |
607
|
|
|
$rowPos++; |
608
|
|
|
$cell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn, $rowPos); |
609
|
|
|
$this->setCellValue($row, $cell->getCoordinate()); |
610
|
|
|
} |
611
|
|
|
$startColumn++; |
612
|
|
|
} |
613
|
|
|
} |
614
|
|
|
} catch (Exception $e) { |
615
|
|
|
$this->error = $e->getMessage(); |
616
|
|
|
return -1; |
617
|
|
|
} |
618
|
|
|
return 1; |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
/** |
622
|
|
|
* Make a 2xN Tab in Sheet |
623
|
|
|
* |
624
|
|
|
* @param string $startCell A1 |
625
|
|
|
* @param array $TDatas array(Title=>val) |
626
|
|
|
* @param bool $boldTitle true if bold titles |
627
|
|
|
* @return int 1 if OK, -1 if KO |
628
|
|
|
*/ |
629
|
|
|
public function setBlock2Columns($startCell, $TDatas = array(), $boldTitle = false) |
630
|
|
|
{ |
631
|
|
|
try { |
632
|
|
|
if (!empty($TDatas)) { |
633
|
|
|
$startCell = $this->workbook->getActiveSheet()->getCell($startCell); |
634
|
|
|
$startColumn = Coordinate::columnIndexFromString($startCell->getColumn()); |
635
|
|
|
$startRow = $startCell->getRow(); |
636
|
|
|
foreach ($TDatas as $title => $val) { |
637
|
|
|
$cell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn, $startRow); |
638
|
|
|
if ($boldTitle) { |
639
|
|
|
$this->setFontStyle(true, $this->styleArray['font']['color']['argb']); |
640
|
|
|
} |
641
|
|
|
$this->setCellValue($title, $cell->getCoordinate()); |
642
|
|
|
if ($boldTitle) { |
643
|
|
|
$this->setFontStyle(false, $this->styleArray['font']['color']['argb']); |
644
|
|
|
} |
645
|
|
|
$cell2 = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn + 1, $startRow); |
646
|
|
|
$this->setCellValue($val, $cell2->getCoordinate()); |
647
|
|
|
$startRow++; |
648
|
|
|
} |
649
|
|
|
} |
650
|
|
|
} catch (Exception $e) { |
651
|
|
|
$this->error = $e->getMessage(); |
652
|
|
|
return -1; |
653
|
|
|
} |
654
|
|
|
return 1; |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
/** |
658
|
|
|
* Enable auto sizing for column range |
659
|
|
|
* |
660
|
|
|
* @param string $firstColumn first column to autosize |
661
|
|
|
* @param string $lastColumn to last column to autosize |
662
|
|
|
* @return int 1 |
663
|
|
|
*/ |
664
|
|
|
public function enableAutosize($firstColumn, $lastColumn) |
665
|
|
|
{ |
666
|
|
|
foreach (range($firstColumn, $lastColumn) as $columnID) { |
667
|
|
|
$this->workbook->getActiveSheet()->getColumnDimension($columnID)->setAutoSize(true); |
668
|
|
|
} |
669
|
|
|
return 1; |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
/** |
673
|
|
|
* Set a value cell and merging it by giving a starting cell and a length |
674
|
|
|
* |
675
|
|
|
* @param string $val Cell value |
676
|
|
|
* @param string $startCell Starting cell |
677
|
|
|
* @param int $length Length |
678
|
|
|
* @param int $offset Starting offset |
679
|
|
|
* @return int|string Coordinate or if KO: -1 |
680
|
|
|
*/ |
681
|
|
|
public function setMergeCellValueByLength($val, $startCell, $length, $offset = 0) |
682
|
|
|
{ |
683
|
|
|
try { |
684
|
|
|
$startCell = $this->workbook->getActiveSheet()->getCell($startCell); |
685
|
|
|
$startColumn = Coordinate::columnIndexFromString($startCell->getColumn()); |
686
|
|
|
if (!empty($offset)) { |
687
|
|
|
$startColumn += $offset; |
688
|
|
|
} |
689
|
|
|
|
690
|
|
|
$startRow = $startCell->getRow(); |
691
|
|
|
$startCell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn, $startRow); |
692
|
|
|
$startCoordinate = $startCell->getCoordinate(); |
693
|
|
|
$this->setCellValue($val, $startCell->getCoordinate()); |
694
|
|
|
|
695
|
|
|
$endCell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($startColumn + ($length - 1), $startRow); |
696
|
|
|
$endCoordinate = $endCell->getCoordinate(); |
697
|
|
|
$this->workbook->getActiveSheet()->mergeCells($startCoordinate . ':' . $endCoordinate); |
698
|
|
|
} catch (Exception $e) { |
699
|
|
|
$this->error = $e->getMessage(); |
700
|
|
|
return -1; |
701
|
|
|
} |
702
|
|
|
return $endCoordinate; |
703
|
|
|
} |
704
|
|
|
} |
705
|
|
|
|
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.