This one took me a while to figure out.
First, create a DynaForm like this:
DynaFormToUploadCsvFile.png (75.65 KiB) Viewed 25694 times
Where there are the following fields:
1. Multiple File with ID "cvsFiles" associated with varaible "csvFiles"
2. Submit Button with ID "showContents"
3. Panel with ID "csvPanel" which has the content:
Code: Select all<table id="csvTable" class="display" width="100%"></table>
4. Submit Button with ID "submit"
5. Hidden field with ID "action"
6. Hidden field with ID "csvData"
Second, add the
dataTables library to the DynaForm. In the
external libs property of the DynaForm, add:
Code: Select allhttps://cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js, https://cdn.datatables.net/1.10.9/css/jquery.dataTables.min.css
Third, add the following JavaScript code to the DynaForm:
Code: Select all$("#showContents").find("button").click(function() {
$("#action").setValue("SHOW_CONTENTS");
});
$("#submit").find("button").click(function() {
$("#action").setValue("");
});
var sData = $("#csvData").getValue();
if (sData == '') {
$("#csvPanel").hide();
}
else {
var aData = JSON.parse(sData);
if (typeof aData != "object" || aData.length < 1) {
alert("Invalid or empty CSV file");
}
else {
var aHeader = aData.shift();
var aColumns = [];
for (i in aHeader) {
aColumns.push( {"title": aHeader[i]} );
}
$('#csvTable').DataTable( {
data: aData,
columns: aColumns
} );
}
}
Then, create the following trigger in the process:
Code: Select all//set to the unique ID of the DynaForm:
$formId = '12208547059961e691679c6060409756';
//possible CSV file types in MIME:
$aMimeCsv = array(
'text/plain',
'application/vnd.ms-excel',
'text/x-csv',
'application/csv',
'application/x-csv',
'text/csv',
'text/comma-separated-values',
'text/x-comma-separated-values',
'text/tab-separated-values'
);
$g = new G();
if (isset(@@action) and @@action == 'SHOW_CONTENTS') {
@=csvData = '';
$aRows = array();
if (!isset(@=csvFiles) or empty(@=csvFiles)) {
$g->SendMessageText('Please upload a comma-separated-value (CSV) file to display its contents.', 'INFO');
PMFRedirectToStep(@@APPLICATION, @%INDEX, 'DYNAFORM', $formId);
}
//construct path to the stored file in the server's file system:
$filename = @=csvFiles[0]['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$path = PATH_DOCUMENT . $g->getPathFromUID(@@APPLICATION) . PATH_SEP .
@=csvFiles[0]['appDocUid'] . '_' . @=csvFiles[0]['version'] . '.' . $ext;
$finfo = new finfo();
$fileMimeType = $finfo->file($path, FILEINFO_MIME_TYPE);
if (!in_array($fileMimeType, $aMimeCsv)) {
$g->SendMessageText("File '$filename' is not a comma-separated-value file. ".
"Please upload a CSV file.", "WARNING");
$d = new AppDocument();
$d->remove(@=csvFiles[0]['appDocUid'], @=csvFiles[0]['version']);
unset(@=csvFiles);
PMFRedirectToStep(@@APPLICATION, @%INDEX, 'DYNAFORM', $formId);
}
ini_set('auto_detect_line_endings',TRUE);
if (($fHandle = fopen($path, "r")) == false) {
$g->SendMessageText("Unable to open file $path for reading. Please delete it and try again.", "ERROR");
PMFRedirectToStep(@@APPLICATION, @%INDEX, 'DYNAFORM', $formId);
}
//In first line figure out whether ',' or ';' used as the delimiter between data
$delimiter = ',';
if (($aData = fgetcsv($fHandle, 0, $delimiter)) == false) {
$g->SendMessageText("File '$filename' is empty. Upload another file.", "WARNING");
$d = new AppDocument();
$d->remove(@=csvFiles[0]['appDocUid'], @=csvFiles[0]['version']);
unset(@=csvFiles);
PMFRedirectToStep(@@APPLICATION, @%INDEX, 'DYNAFORM', $formId);
}
if (count($aData) == 1) {
$delimiter = ';';
rewind($fHandle);
$aData = fgetcsv($fHandle, 0, $delimiter);
}
$aRows[] = $aData;
while (($aData = fgetcsv($fHandle, 0, $delimiter)) !== false) {
$aRows[] = $aData;
}
@=csvData = json_encode($aRows);
fclose($fHandle);
PMFRedirectToStep(@@APPLICATION, @%INDEX, 'DYNAFORM', $formId);
}
Set this trigger to fire
before the step following the DynaForm to upload a CSV file (or
before assignment if the last step in the task). The trigger should NOT be fired immediately after the DynaForm, because at that point the CSV file will not yet be saved to the database or the server's file system.
This trigger will use PMFRedirectToStep() to return to the same DynaForm and display the contents of the CSV file in the panel. It will not allow the contents of the file to be changed. If needing to allow the user to change the contents, use a grid instead of a panel.
Then, run a case and select a CSV file to upload.
SelectCsvFileBeforeDisplaying.png (9.99 KiB) Viewed 25694 times
If the user clicks on the "Submit" button then the case will continue to the next step in the task, but if the user clicks on the "Show Contents" button, then the subsequent trigger will open the CSV file and place its contents in an array which is serialized as a JSON string in the csvData variable. Finally, the trigger calls PMFRedirectToStep() to redisplay the same DynaForm, with the contents of the CSV file shown in the panel below.
CsvFileDisplayedInPanel.png (34.88 KiB) Viewed 25694 times
To try out a sample process containing this code, download and import the following process:
(31.23 KiB) Downloaded 610 times
Note: This code will not work in the ProcessMaker Mobile App, because it doesn't support PMFRedirectToStep(). If needing to display other types of spreadsheet files (Excel, OpenDocument Spreadsheet, etc.) in the panel, then the
PHPExcel library can be imported into the trigger and used to open other types of spreadsheets as shown in this
example.