Commit 71cbbf1b authored by Carsten  Rose's avatar Carsten Rose
Browse files

F4922 / Excel Import: First successful run with dynamic data 'p:?id=excelexport'

parent 4e80990e
Pipeline #672 passed with stage
in 1 minute and 33 seconds
......@@ -6071,24 +6071,25 @@ Download
Download offers:
* download a single file (any type),
* concatenate several files (uploaded) and/or web pages (=HTML to PDF) into one PDF output file,
* create a ZIP archive, filled with several files ('uploaded' or 'HTML to PDF'-converted).
* Single file - download a single file (any type),
* PDF create - one or concatenate several files (uploaded) and/or web pages (=HTML to PDF) into one PDF output file,
* ZIP archive - filled with several files ('uploaded' or 'HTML to PDF'-converted).
* Excel - created from scratch or fill a template xlsx with database values.
The downloads are SIP protected. Only the current user can use the link to download files.
By using the `_link` columnname:
By using the `_link` column name:
* the option `d:...` initiate creating the download link and optional specifies an export filename,
* the optional `M:...` (Mode) specifies the export type (file, pdf, zip),
* the optional `M:...` (Mode) specifies the export type (file, pdf, zip, export),
* setting `s:1` is mandatory for the download function,
* the alttext `a:...` specifies a message in the download popup.
By using `_pdf`, `_Pdf`, `_file`, `_File`, `_zip`, `_Zip` as columnname, the options `d`, `m` and `s`
will be set by automatically.
By using `_pdf`, `_Pdf`, `_file`, `_File`, `_zip`, `_Zip`, `excel` as columnname, the options `d`, `m` and `s`
will be set.
All files will be read by PHP - therefore the directory might be protected against direct web access. This way is the
preferred way to offer secure downloads via QFQ.
All files will be read by PHP - therefore the directory might be protected against direct web access. This is the
preferred option to offer secure downloads via QFQ.
In case the download needs a persistant URL (no SIP, no user session), a regular
link, pointing directly to a file, have to be used - the download functionality described here is not appropriate for
......@@ -6103,21 +6104,20 @@ Parameter and (element) sources
* *exportFilename* = <filename for save as> - Name, offered in the 'File save as' browser dialog. Default: 'output.<ext>'.
If there is no `exportFilename` defined, then the original filename is taken.
If there is no `exportFilename` defined, then the original filename is taken (if there is one, else: output...).
The user typically expects meaningful and distinct filenames for different download links.
The user typically expects meaningful and distinct file names for different download links.
* *popupMessage*: `a:<text>` - will be displayed in the popup window during download. If the creating/download is fast, the window might disappear quickly.
* *mode*: `M:<mode>`
* *mode* = <file | pdf | zip> - This parameter is optional and can be skipped in most situations. Mandatory
for 'zip'.
* *mode* = <file | pdf | zip | excel>
* If `M:file`, the mime type is derived dynamically from the specified file. In this mode, only one element source
is allowed per download link (no concatenation).
* In case of multiple element sources, only `pdf` or `zip` is supported.
* In case of multiple element sources, only `pdf`, `zip` and `excel` (template mode) is supported.
* If `M:zip` is used together with `p:...`, `U:...` or `u:..`, those HTML pages will be converted to PDF. Those files
get generic filenames inside the archive.
* If not specified, the **default** 'Mode' depends on the number of specified element sources (=file or web page):
......@@ -6125,7 +6125,8 @@ Parameter and (element) sources
* If only one `file` is specifed, the default is `file`.
* If there is a) a page defined or b) multiple elements, the default is `pdf`.
* *element sources* - for `M:pdf` or `M:zip`, all of the following three element sources might be specified multiple times. Any combination and order of the three options are allowed.
* *element sources* - for `M:pdf` or `M:zip`, all of the following three element sources might be specified multiple times.
Any combination and order of the three options are allowed.
* *file*: `F:<pathFileName>` - relative or absolute pathFileName offered for a) download (single), or to be concatenated
in a PDF or ZIP.
......@@ -6203,6 +6204,8 @@ Example `_pdf`, `_zip`: ::
Use the `--print-media-type` as wkhtml option to access the page with media type 'printer'. Depending on the website
configuration this switches off navigation and background images.
Rendering PDF letters
^^^^^^^^^^^^^^^^^^^^^
......@@ -6312,6 +6315,101 @@ is allowed to access: ::
page.10.value = Please access from localhost or log in as 'admin' user.
[global]
.. _excel-export:
Excel export
^^^^^^^^^^^^
'On the fly'-creation of an excel file. The file is build in the moment when the user clicks on the download button.
Mode:
* NEW: The export file will be completely build from scratch.
* TEMPLATE: The export file is based on an earlier saved xlsx file (template). The template is unchanged.
Injecting the data is done in the same way in both modes . The only difference is by specifying a xlsx file which will
be used as an template.
If the export file has to be customized (colors, pictures, headlines, ...), the TEMPLATE mode is the preferred option.
Setup
'''''
* Create a special column name `_excel` (or `_link`) in QFQ/Report. As a source, define a T3 page, which have to deliver
the dynamic content. ::
# New
SELECT CONCAT('d:final.xlsx|M:excel|s:1|t:Excel (new)|p:?id=exceldata') AS _link
# Template
SELECT CONCAT('d:final.xlsx|M:excel|s:1|t:Excel (template)|F:fileadmin/template.xlsx|p:?id=exceldata&arg1=hello') AS _link
* Create a T3 page which delivers the content.
* Disable all HTML header and wrapping code on that page. Typoscript setup: ::
config.disableAllHeaderCode = 1
tt_content.stdWrap >
page >
page = PAGE
[usergroup = *] || [IP = 127.0.0.1,192.168.1.*]
page.10 < styles.content.get
[else]
page.10 = TEXT
page.10.value = access forbidden
[global]
* Use the regular QFQ Report syntax to create some output.
* The newline character ist CHAR(10).
* One option per line.
* Empty will be skipped.
* Lines starting with '#' will be skipped (comments)
* Separate <keyword> and <value> by '='.
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| Keyword | Example | Description |
+=============+================+===================================================================================================+
| 'worksheet' | worksheet=main | Select a worksheet in case the excel file has multiple of them. |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'mode' | mode=insert | Values: insert,overwrite. |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'position' | position=A1 | Default is 'A1'. Use the excel notation. |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'row' | row | Start a new row. |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'str', 's' | s=hello world | Set the given string on the given position. The current position will be shiftet one to the right |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'f' | f==SUM(A5:C6) | Set a formular on the given position. The current position will be shiftet one to the right |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
| 'n' | n=123 | Set number on the given position. The current position will be shiftet one to the right |
+-------------+----------------+---------------------------------------------------------------------------------------------------+
Create a output like this: ::
position=D11
s=Hello
s=World
s=First Line
row
s=Second line
n=123
This fills D11, E11, F11, D12
In Report Syntax: ::
10.sql = SELECT 'position=D11' AS _XLS,
's=Hello' AS _XLS,
's=World' AS _XLS,
's=First Line' AS _XLS,
+ 'row' AS _XLS,
's=Second line' AS _XLS,
'n=123' AS _XLS,
.. _drag_and_drop:
Drag and drop
......
......@@ -1294,20 +1294,21 @@ const COLUMN_PAGEH = 'pageh';
const COLUMN_PAGEI = 'pagei';
const COLUMN_PAGEN = 'pagen';
const COLUMN_PAGES = 'pages';
const COLUMN_PDF = 'pdf';
const COLUMN_FILE = 'file';
const COLUMN_ZIP = 'zip';
const COLUMN_MONITOR = 'monitor';
const COLUMN_EXCEL = 'excel';
const COLUMN_NL2BR = 'nl2br';
const COLUMN_HTMLENTITIES = 'htmlentities';
const COLUMN_STRIPTAGS = 'striptags';
const COLUMN_MIME_TYPE = 'mimeType'; // Will also be used to identify equal named columns in upload record.
const COLUMN_FILE_SIZE = 'fileSize'; // Will also be used to identify equal named columns in upload record.
const COLUMN_IMPORT = "import";
const COLUMN_EXCEL_STRING = 'XLSstring';
const COLUMN_EXCEL_NUMERIC = 'XLSnumeric';
const COLUMN_EXCEL_PLAIN = 'XLS';
const COLUMN_WRAP_TOKEN = '+';
......@@ -1349,12 +1350,14 @@ const EXCEL_MODE_INSERT = 'insert';
const EXCEL_MODE_OVERWRITE = 'overwrite';
const EXCEL_POSITION = 'position';
const EXCEL_ROW = 'row';
const EXCEL_STRING = 'string';
const EXCEL_NUMBER = 'number';
const EXCEL_CURRENCY = 'currency';
const EXCEL_DATE = 'date';
const EXCEL_DATETIME = 'datetime';
const EXCEL_TIME = 'time';
const EXCEL_STRING2 = 'str';
const EXCEL_STRING = 's';
const EXCEL_FORMULA = 'f';
const EXCEL_NUMERIC = 'n';
const EXCEL_BOOL = 'b';
const EXCEL_NULL = 'null';
const EXCEL_INLINE = 'inlineStr';
const EXCEL_ERROR = 'e';
const MONITOR_TAIL_DEFAULT = 30;
const MONITOR_APPEND_DEFAULT = 0;
......
......@@ -93,8 +93,8 @@ class Excel {
$worksheet = $spreadsheet->getActiveSheet();
$pos = 'A1';
if(!OnString::splitExcelPos($pos, $posColumn, $posRow)){
throw new downloadException("Invalid cell coordinates: " . $pos, ERROR_EXCEL_INVALID_COORDINATES);
if (!OnString::splitExcelPos($pos, $posColumn, $posRow)) {
throw new downloadException("Invalid cell coordinates: " . $pos, ERROR_EXCEL_INVALID_COORDINATES);
}
$arr = explode(PHP_EOL, $data);
foreach ($arr as $line) {
......@@ -107,6 +107,8 @@ class Excel {
}
$token = explode(':', $line, 2);
$key=$token[0];
$value=$token[1];
switch ($token[0]) {
case EXCEL_WORKSHEET:
throw new downloadException("Not implemented: " . $token[0], ERROR_NOT_IMPLEMENTED);
......@@ -120,8 +122,8 @@ class Excel {
throw new downloadException("Position argument is empty", ERROR_EXCEL_POSITION_ARGUMENT_EMPTY);
}
if(!OnString::splitExcelPos($token[1], $posColumn, $posRow)){
throw new downloadException("Invalid cell coordinates: " . $pos, ERROR_EXCEL_INVALID_COORDINATES);
if (!OnString::splitExcelPos($token[1], $posColumn, $posRow)) {
throw new downloadException("Invalid cell coordinates: " . $token[1], ERROR_EXCEL_INVALID_COORDINATES);
}
break;
......@@ -130,16 +132,24 @@ class Excel {
break;
case EXCEL_STRING:
$worksheet->setCellValue($posColumn . $posRow, $token[1]);
case EXCEL_STRING2:
case EXCEL_FORMULA:
case EXCEL_NUMERIC:
case EXCEL_BOOL:
case EXCEL_NULL:
case EXCEL_INLINE:
case EXCEL_ERROR:
$spreadsheet->getActiveSheet()
->setCellValueExplicit(
$posColumn . $posRow,
$token[1],
$token[0]
);
$posColumn = $this->nextColumn($posColumn);
break;
case EXCEL_NUMBER:
case EXCEL_CURRENCY:
case EXCEL_DATE:
case EXCEL_DATETIME:
case EXCEL_TIME:
throw new downloadException("Not implemented: " . $token[0], ERROR_NOT_IMPLEMENTED);
default:
throw new downloadException("Excel Export: unknown token " . $token[0], ERROR_UNKNOWN_TOKEN);
}
}
......
......@@ -786,9 +786,9 @@ class Link {
switch ($mode) {
case DOWNLOAD_MODE_PDF:
case DOWNLOAD_MODE_ZIP:
case DOWNLOAD_MODE_EXCEL:
break;
case DOWNLOAD_MODE_FILE:
case DOWNLOAD_MODE_EXCEL:
if ($cnt > 1) {
throw new UserFormException("With 'downloadMode' = 'file' only one element source is allowed.", ERROR_DOWNLOAD_UNEXPECTED_NUMBER_OF_SOURCES);
}
......
......@@ -790,6 +790,15 @@ class Report {
$dataImport = new DataImport($this->db);
$content = $dataImport->process('typo3conf/ext/qfq/qfq/qfq/sample.xlsx', 'test');
break;
case COLUMN_EXCEL_PLAIN:
$content .= $columnValue . PHP_EOL;
break;
case COLUMN_EXCEL_STRING:
$content .= EXCEL_STRING . ':' . $columnValue . PHP_EOL;
break;
case COLUMN_EXCEL_NUMERIC:
$content .= EXCEL_NUMERIC . ':' . $columnValue . PHP_EOL;
break;
case "bullet":
if ($columnValue === '') {
......@@ -1179,7 +1188,10 @@ class Report {
return '';
}
$columNameToMode = [COLUMN_PDF => DOWNLOAD_MODE_PDF, COLUMN_FILE => DOWNLOAD_MODE_FILE, COLUMN_ZIP => DOWNLOAD_MODE_ZIP, COLUMN_EXCEL => DOWNLOAD_MODE_EXCEL];
$columNameToMode = [COLUMN_PDF => DOWNLOAD_MODE_PDF,
COLUMN_FILE => DOWNLOAD_MODE_FILE,
COLUMN_ZIP => DOWNLOAD_MODE_ZIP,
COLUMN_EXCEL => DOWNLOAD_MODE_EXCEL];
$param = explode('|', $columnValue);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment