dataview - excel export

This commit is contained in:
Ralph Soika 2025-05-12 14:24:13 +02:00
parent 303448d766
commit 6cfea74397
5 changed files with 593 additions and 77 deletions

View file

@ -23,22 +23,30 @@
*******************************************************************************/ *******************************************************************************/
package org.imixs.workflow.office.dataview; package org.imixs.workflow.office.dataview;
import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.imixs.archive.core.SnapshotService;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection; import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.ModelException; import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.exceptions.QueryException;
import org.imixs.workflow.faces.data.ViewController; import org.imixs.workflow.faces.data.ViewController;
import org.imixs.workflow.faces.data.ViewHandler; import org.imixs.workflow.faces.data.ViewHandler;
import org.imixs.workflow.office.forms.CustomFormController; import org.imixs.workflow.office.forms.CustomFormController;
import org.imixs.workflow.office.forms.CustomFormSection; import org.imixs.workflow.office.forms.CustomFormSection;
import com.alexanderlogistics.mahnlauf.InkassoExportAdapter;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.Conversation; import jakarta.enterprise.context.Conversation;
import jakarta.enterprise.context.ConversationScoped; import jakarta.enterprise.context.ConversationScoped;
@ -69,6 +77,10 @@ import jakarta.servlet.http.HttpServletRequest;
public class DataViewController extends ViewController { public class DataViewController extends ViewController {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final String ERROR_CONFIG = "CONFIG_ERROR";
public static final int MAX_ROWS = 3000;
private List<CustomFormSection> sections = null; private List<CustomFormSection> sections = null;
private List<ItemCollection> viewItemDefinitions = null; private List<ItemCollection> viewItemDefinitions = null;
protected ItemCollection dataDefinition = null; protected ItemCollection dataDefinition = null;
@ -85,6 +97,12 @@ public class DataViewController extends ViewController {
@Inject @Inject
private DocumentService documentService; private DocumentService documentService;
@Inject
private WorkflowService workflowService;
@Inject
SnapshotService snapshotService;
@Inject @Inject
CustomFormController customFormController; CustomFormController customFormController;
@ -111,9 +129,7 @@ public class DataViewController extends ViewController {
* This method loads the custom form sections * This method loads the custom form sections
*/ */
public void onLoad() { public void onLoad() {
String cacheid = null; String cacheid = null;
logger.info("> onload...");
// Important: start a new conversation beause of the usage of the // Important: start a new conversation beause of the usage of the
// CustomFormController! // CustomFormController!
@ -134,7 +150,7 @@ public class DataViewController extends ViewController {
dataDefinition = documentService.load(uniqueid); dataDefinition = documentService.load(uniqueid);
} }
logger.info("> cacheid=" + cacheid); logger.finest("> cacheid=" + cacheid);
if (cacheid != null && !cacheid.isEmpty()) { if (cacheid != null && !cacheid.isEmpty()) {
filter = dataViewCache.get(cacheid); filter = dataViewCache.get(cacheid);
} else { } else {
@ -145,13 +161,21 @@ public class DataViewController extends ViewController {
// Init new Filter.... // Init new Filter....
if (dataDefinition != null) { if (dataDefinition != null) {
filter.setItemValue("txtWorkflowEditorCustomForm", dataDefinition.getItemValue("form")); filter.setItemValue("txtWorkflowEditorCustomForm", dataDefinition.getItemValue("form"));
filter.setItemValue("name", dataDefinition.getItemValueString("name"));
filter.setItemValue("description", dataDefinition.getItemValueString("description"));
viewItemDefinitions = DataViewDefinitionController viewItemDefinitions = DataViewDefinitionController
.computeDataViewItemDefinitions(dataDefinition); .computeDataViewItemDefinitions(dataDefinition);
customFormController.computeFieldDefinition(filter); customFormController.computeFieldDefinition(filter);
sections = customFormController.getSections(); sections = customFormController.getSections();
logger.info(" < cached page index=" + filter.getItemValueInteger("pageIndex")); // Update View Handler settings
String sortBy = dataDefinition.getItemValueString("sort.by");
if (sortBy.isEmpty()) {
sortBy = "$modified";
}
this.setSortBy(sortBy);
this.setSortReverse(dataDefinition.getItemValueBoolean("sort.reverse"));
this.setPageIndex(filter.getItemValueInteger("pageIndex")); this.setPageIndex(filter.getItemValueInteger("pageIndex"));
if (!filter.getItemValueString("query").isEmpty()) { if (!filter.getItemValueString("query").isEmpty()) {
query = filter.getItemValueString("query"); query = filter.getItemValueString("query");
@ -229,7 +253,7 @@ public class DataViewController extends ViewController {
// Replace all occurrences in the query case-insensitive. // Replace all occurrences in the query case-insensitive.
query = query.replaceAll("(?i)\\{" + Pattern.quote(itemName) + "\\}", itemValue); query = query.replaceAll("(?i)\\{" + Pattern.quote(itemName) + "\\}", itemValue);
} }
logger.info("query=" + query); logger.finest("query=" + query);
filter.setItemValue("query", query); filter.setItemValue("query", query);
// Prefetch data to update total count and page count // Prefetch data to update total count and page count
@ -246,29 +270,6 @@ public class DataViewController extends ViewController {
return query; return query;
} }
// /**
// * Returns the current workItem. If no workitem is defined the method
// * Instantiates a empty ItemCollection.
// *
// * @return - current workItem or null if not set
// */
// public ItemCollection getData() {
// // do initialize an empty workItem here if null
// if (data == null) {
// reset();
// }
// return data;
// }
// /**
// * Set the current workItem
// *
// * @param workitem - new reference or null to clear the current workItem.
// */
// public void setData(ItemCollection document) {
// this.data = document;
// }
/** /**
* This method navigates back in the page index and caches the current page * This method navigates back in the page index and caches the current page
* index * index
@ -285,7 +286,6 @@ public class DataViewController extends ViewController {
public void forward() { public void forward() {
viewHandler.forward(this); viewHandler.forward(this);
filter.setItemValue("pageIndex", this.getPageIndex()); filter.setItemValue("pageIndex", this.getPageIndex());
logger.info("-> forward to page " + this.getPageIndex());
} }
/** /**
@ -297,9 +297,97 @@ public class DataViewController extends ViewController {
((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()) ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest())
.getSession().getMaxInactiveInterval() * 1000); .getSession().getMaxInactiveInterval() * 1000);
conversation.begin(); conversation.begin();
logger.log(Level.INFO, "......start new conversation, id={0}", logger.log(Level.FINEST, "......start new conversation, id={0}",
conversation.getId()); conversation.getId());
} }
} }
/**
* Exports data into a excel template processed by apache-poi
*
* @throws PluginException
* @throws QueryException
*/
public String export() throws PluginException, QueryException {
// build query and prepare dataset
run();
SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMddHHmm");
String targetFileName = dataDefinition.getItemValueString("poi.targetFilename");
if (targetFileName.isEmpty()) {
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
"Missing Excel Export definition - check configuration!");
}
logger.info("start export : " + targetFileName + "...");
logger.fine(query);
// load template
FileData fileData = loadTemplate();
if (fileData == null) {
// we did not found the template!
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
"Missing Excel Export Template - check DataView definition!");
}
targetFileName = targetFileName + "_" + dateformat.format(new Date()) + ".xlsx";
try {
// test if query exceeds max count
int totalCount = documentService.count(query);
if (totalCount > MAX_ROWS) {
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
"Data can not be exported into Excel because dataset exceeds " + MAX_ROWS + " rows!");
}
String sortBy = dataDefinition.getItemValueString("sort.by");
if (sortBy.isEmpty()) {
sortBy = "$modified"; // default
}
List<ItemCollection> invoices = documentService.find(query, MAX_ROWS, 0, sortBy,
dataDefinition.getItemValueBoolean("sort.reverse"));
if (invoices.size() > 0) {
String referenceCell = dataDefinition.getItemValueString("poi.referenceCell");
DataViewPOIHelper.insertDataRows(invoices, referenceCell, viewItemDefinitions, fileData);
}
// create a temp event
ItemCollection event = new ItemCollection().setItemValue("txtActivityResult",
dataDefinition.getItemValue("poi.update"));
ItemCollection poiConfig = workflowService.evalWorkflowResult(event, "poi-update", dataDefinition,
false);
DataViewPOIHelper.poiUpdate(filter, fileData, poiConfig, workflowService);
fileData.setName(targetFileName);
// See:
// https://stackoverflow.com/questions/9391838/how-to-provide-a-file-download-from-a-jsf-backing-bean
DataViewPOIHelper.downloadExcelFile(fileData);
} catch (IOException | QueryException e) {
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
"Failed to generate Excel Export: " + e.getMessage());
}
// return "/pages/admin/excel_export_rechnungsausgang.jsf?faces-redirect=true";
return "";
}
/**
* This method returns the first excel poi template from the Data Definition
*
* @param name in attribute txtname
*
*
*/
private FileData loadTemplate() {
// first filename
List<FileData> fileDataList = dataDefinition.getFileData();
if (fileDataList != null && fileDataList.size() > 0) {
String fileName = fileDataList.get(0).getName();
return snapshotService.getWorkItemFile(dataDefinition.getUniqueID(), fileName);
}
// no file data available!
return null;
}
} }

View file

@ -0,0 +1,356 @@
/*******************************************************************************
* Imixs Workflow Technology
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* 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 2
* 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 can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika
*
*******************************************************************************/
package org.imixs.workflow.office.dataview;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.util.XMLParser;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
/**
* The DataViewPOIHelper provides methods to update a excel template with the
* help of the Apache POI framework.
*
*
* @author rsoika
* @version 1.0
*/
public class DataViewPOIHelper {
private static Logger logger = Logger.getLogger(DataViewPOIHelper.class.getName());
public static final String ERROR_CONFIG = "CONFIG_ERROR";
/**
* Helper method to initialize a file download
*
* @throws IOException
*/
public static void downloadExcelFile(FileData fileData) throws IOException {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.responseReset();
externalContext.setResponseContentType("application/vnd.ms-excel");
externalContext.setResponseContentLength(fileData.getContent().length);
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileData.getName() + "\"");
OutputStream output = externalContext.getResponseOutputStream();
// Now you can write the InputStream of the file to the above OutputStream the
// usual way.
output.write(fileData.getContent());
facesContext.responseComplete(); // Important! Otherwise Faces will attempt to render the response which
// obviously will fail since it's already written with a file and closed.
}
/**
* This helper method inserts a row for each invoice
*
* @throws PluginException
*/
public static void insertDataRows(List<ItemCollection> dataset, String referenceCell,
List<ItemCollection> viewItemDefinitions,
FileData fileData) throws PluginException {
// load XSSFWorkbook
try (InputStream imputStream = new ByteArrayInputStream(fileData.getContent())) {
XSSFWorkbook doc = new XSSFWorkbook(imputStream);
// NOTE: we only take the first sheet !
XSSFSheet sheet = doc.getSheetAt(0);
CellReference cr = new CellReference(referenceCell);
XSSFRow referenceRow = sheet.getRow(cr.getRow());
int referenceRowPos = referenceRow.getRowNum() + 1;
int rowPos = referenceRowPos;
// int lastRow = sheet.getLastRowNum();
int lastRow = 999;
logger.finest("Last rownum=" + lastRow);
sheet.shiftRows(rowPos, lastRow, dataset.size(), true, true);
for (ItemCollection workitem : dataset) {
logger.finest("......copy row...");
// now create a new line..
XSSFRow row = sheet.createRow(rowPos);
row.copyRowFrom(referenceRow, new CellCopyPolicy());
// insert values
int cellNum = 0;
for (ItemCollection itemDef : viewItemDefinitions) {
String type = itemDef.getItemValueString("item.type");
String name = itemDef.getItemValueString("item.name");
switch (type) {
case "xs:double":
row.getCell(cellNum).setCellValue(workitem.getItemValueDouble(name));
break;
case "xs:float":
row.getCell(cellNum).setCellValue(workitem.getItemValueFloat(name));
break;
case "xs:int":
row.getCell(cellNum).setCellValue(workitem.getItemValueInteger(name));
break;
case "xs:date":
row.getCell(cellNum).setCellValue(workitem.getItemValueDate(name));
break;
default:
row.getCell(cellNum).setCellValue(workitem.getItemValueString(name));
}
cellNum++;
}
rowPos++;
}
// delete reference row
sheet.shiftRows(referenceRowPos, lastRow + dataset.size(), -1, true, true);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// write back the file
doc.write(byteArrayOutputStream);
doc.close();
byte[] newContent = byteArrayOutputStream.toByteArray();
fileData.setContent(newContent);
} catch (IOException e) {
throw new PluginException(DataViewPOIHelper.class.getSimpleName(), ERROR_CONFIG,
"failed to update excel export: " + e.getMessage());
}
}
/**
* This helper method applies the POI update defintiions a row for each invoice
*
* @throws PluginException
*/
public static void poiUpdate(ItemCollection dataDefinition, FileData fileData,
ItemCollection poiConfig, WorkflowService workflowService) throws PluginException {
// update $modified for Now function
dataDefinition.setItemValue("$modified", new Date());
if (poiConfig == null || !poiConfig.hasItem("findreplace")) {
// no config found
return;
}
List<String> replaceDevList = poiConfig.getItemValue("findreplace");
String eval = poiConfig.getItemValueString("eval");
// load XSSFWorkbook
try (InputStream imputStream = new ByteArrayInputStream(fileData.getContent())) {
XSSFWorkbook workbook = new XSSFWorkbook(imputStream);
// NOTE: we only take the first sheet !
XSSFSheet sheet = workbook.getSheetAt(0);
updateXSSFWorkbook(workbook, dataDefinition, replaceDevList, workflowService);
// Update Eval list
if (eval != null && !eval.isEmpty()) {
// iterate over all cells to be evaluated
String[] cellPositions = eval.split(";");
for (String cellPos : cellPositions) {
evalXSSFSheet(workbook, sheet, cellPos);
}
logger.fine("formula evaluation completed");
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// write back the file
workbook.write(byteArrayOutputStream);
workbook.close();
byte[] newContent = byteArrayOutputStream.toByteArray();
fileData.setContent(newContent);
} catch (IOException e) {
throw new PluginException(DataViewPOIHelper.class.getSimpleName(), ERROR_CONFIG,
"failed to update excel export: " + e.getMessage());
}
}
/**
* Returns a Cell by name or an optional absolute cell postion
* <p>
* Examples for refs are 'A1', 'AB3', 'MyCell' where 'MyCell' is a named cell.
* <p>
*
*/
public static XSSFCell getCellByRef(XSSFWorkbook doc, XSSFSheet sheet, String cellReference) {
XSSFCell cell = null;
// first we test if the cellName is a named cell
Name aNamedCell = doc.getName(cellReference);
if (aNamedCell != null) {
// yes its a named cell so we need to get the referrer Formula
logger.finest("...resolving named cell = " + aNamedCell.getNameName());
cellReference = aNamedCell.getRefersToFormula();
// now we can find the cell by its ref
}
CellReference cr = new CellReference(cellReference);
XSSFRow row = sheet.getRow(cr.getRow());
if (row == null) {
logger.severe("Unable to resolve cell ref '" + cellReference + "'!");
return null;
}
cell = row.getCell(cr.getCol());
return cell;
}
/**
* This method updates the XSSFWorkbook document. The method can be overwritten
* by subclasses to add additional logic
*
* @param workbook
* @param workitem
* @param replaceDevList
* @throws PluginException
*/
public static void updateXSSFWorkbook(XSSFWorkbook workbook, ItemCollection workitem, List<String> replaceDevList,
WorkflowService workflowService)
throws PluginException {
logger.fine("XSSFWorkbook loaded");
// NOTE: we only take the first sheet !
XSSFSheet sheet = workbook.getSheetAt(0);
for (String entityDev : replaceDevList) {
ItemCollection entityData = XMLParser.parseItemStructure(entityDev);
if (entityData != null) {
String find = entityData.getItemValueString("find");
String replace = entityData.getItemValueString("replace");
replace = workflowService.adaptText(replace, workitem);
// optional itename
String itemname = entityData.getItemValueString("itemname");
// replace with item value?
if (!itemname.isEmpty()) {
List<?> valueList = workitem.getItemValue(itemname);
if (valueList.size() > 0) {
// provide the first value only
replaceXSSFSheetItemValue(workbook, sheet, find, valueList.get(0));
}
} else {
replaceXSSFSheetStringValue(workbook, sheet, find, replace);
}
}
}
}
/**
* Helper method replaces a given cell of a XSSFSheet with a typed item value
*
* @throws PluginException
*/
public static void replaceXSSFSheetItemValue(XSSFWorkbook doc, XSSFSheet sheet, String find, Object itemValue)
throws PluginException {
logger.finest("update cell " + find);
XSSFCell cell = getCellByRef(doc, sheet, find);
if (cell == null) {
logger.warning("Cell " + find + " not found.");
return;
}
if (itemValue instanceof Date) {
cell.setCellValue((Date) itemValue);
} else if (itemValue instanceof Double) {
cell.setCellValue((Double) itemValue);
} else {
// default to text
cell.setCellValue(itemValue.toString());
}
}
/**
* Helper method replaces a given cell of a XSSFSheet with a string value
*
* @throws PluginException
*/
private static void replaceXSSFSheetStringValue(XSSFWorkbook doc, XSSFSheet sheet, String find, String replace)
throws PluginException {
logger.finest("update cell " + find);
XSSFCell cell = getCellByRef(doc, sheet, find);
if (cell == null) {
logger.warning("Cell " + find + " not found.");
return;
}
try {
// we try to set first as float value if possible
float f = Float.parseFloat(replace);
cell.setCellValue(f);
} catch (NumberFormatException e) {
// set value as string
cell.setCellValue(replace);
}
}
/**
* Evaluates a given list of cells in a given XSWorkbook
*
* @param doc
* @param sheet
* @param cell
* @throws PluginException
*/
public static void evalXSSFSheet(XSSFWorkbook doc, XSSFSheet sheet, String cell) throws PluginException {
FormulaEvaluator evaluator = doc.getCreationHelper().createFormulaEvaluator();
XSSFCell c = getCellByRef(doc, sheet, cell);
if (c == null) {
logger.warning("Cell " + cell + " not found.");
return;
}
if (c.getCellType() == CellType.FORMULA) {
logger.finest("...eval cell " + cell);
try {
CellType evalResult = evaluator.evaluateFormulaCell(c);
if (evalResult == CellType.ERROR) {
logger.warning("...unable to evaluate cell " + cell);
}
} catch (Exception poie) {
logger.warning("...failed to evaluate cell " + cell + " : " + poie.getMessage());
}
}
}
}

View file

@ -10,10 +10,12 @@
<f:viewAction action="#{dataViewDefinitionController.onLoad()}" /> <f:viewAction action="#{dataViewDefinitionController.onLoad()}" />
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<f:view> <f:view>
<h:form id="textblock_form_id" pt:autocomplete="on" enctype="multipart/form-data"> <h:form id="dataview_definition_form_id" pt:autocomplete="on" enctype="multipart/form-data">
<div class="imixs-form"> <div class="imixs-form">
<div class="imixs-header"> <div class="imixs-header">
@ -55,11 +57,8 @@
</p> </p>
<dl> <dl>
<dt> <dt>
Name:<span class="imixs-required"> * Name:<span class="imixs-required"> * </span>
</span>
</dt> </dt>
<dd> <dd>
<h:inputText required="true" id="txtname_id" <h:inputText required="true" id="txtname_id"
value="#{dataViewDefinitionController.data.item['Name']}" /> value="#{dataViewDefinitionController.data.item['Name']}" />
@ -88,6 +87,28 @@
</dd> </dd>
</dl> </dl>
</div> </div>
<div class="imixs-form-section-2">
<dl>
<dt>
Sort By:
</dt>
<dd>
<h:inputText required="true"
value="#{dataViewDefinitionController.data.item['sort.by']}" />
</dd>
</dl>
<dl>
<dt>
Reverse Order:
</dt>
<dd>
<h:selectBooleanCheckbox required="false" label=""
value="#{dataViewDefinitionController.data.item['sort.reverse']}">
</h:selectBooleanCheckbox>
</dd>
</dl>
</div>
@ -102,7 +123,8 @@
values. Each item of values. Each item of
the attribute list can define an optional label, xs datatype and format. the attribute list can define an optional label, xs datatype and format.
<br /> <br />
Convert - xml datatypes: xs:string (default), xs:decimal, xs:date, Convert - xml datatypes: xs:string (default), xs:int, xs:double, xs:float,
xs:date,
xs:dateTime, xs:dateTime,
xs:anyURI xs:anyURI
@ -212,7 +234,7 @@
<div id="tab-3"> <div id="tab-3">
<div class="imixs-form-panel"> <div class="imixs-form-panel">
<div class="imixs-form-section-1"> <div class="imixs-form-section-2">
<h1><span class="typcn typcn-news"></span> Template<span <h1><span class="typcn typcn-news"></span> Template<span
style="font-size: 1rem;margin-left:20px;"> style="font-size: 1rem;margin-left:20px;">
<h:outputLink <h:outputLink
@ -221,10 +243,35 @@
style="font-size: 1.2rem;"></span> Test View style="font-size: 1.2rem;"></span> Test View
</h:outputLink> </h:outputLink>
</span></h1> </span></h1>
<dl> <p>
<span class="typcn typcn-lightbulb"></span>
The 'Target Name' defines the name of the file download. The 'Reference Cell
marks the row to insert the dataset. POI update Definitions are optional.
</p>
<dl> <dl>
<dt> <dt>
POI Update: Target Name:
</dt>
<dd>
<h:inputText
value="#{dataViewDefinitionController.data.item['poi.targetfilename']}" />
</dd>
</dl>
<dl>
<dt>
Reference Cell:
</dt>
<dd>
<h:inputText style="width: 5em;"
value="#{dataViewDefinitionController.data.item['poi.referenceCell']}" />
</dd>
</dl>
</div>
<div class="imixs-form-section-1">
<dl>
<dt>
POI Definition:
</dt> </dt>
<dd> <dd>
<h:inputTextarea <h:inputTextarea
@ -233,13 +280,22 @@
</dd> </dd>
</dl> </dl>
<div class="textblock-file-input" style="width: 50%;">
<dl>
<dt>
Source File :
</dt>
<dd>
<i:imixsFileUpload showattachments="true" <i:imixsFileUpload showattachments="true"
workitem="#{dataViewDefinitionController.data}" workitem="#{dataViewDefinitionController.data}"
context_url="#{facesContext.externalContext.requestContextPath}/api/snapshot/#{dataViewDefinitionController.data.item['$uniqueid']}" /> context_url="#{facesContext.externalContext.requestContextPath}/api/snapshot/#{dataViewDefinitionController.data.item['$uniqueid']}" />
</div>
</dd>
</dl> </dl>
</div> </div>
</div> </div>
</div> </div>
@ -277,6 +333,7 @@
} }
/*]]>*/ /*]]>*/
</script> </script>

View file

@ -9,14 +9,39 @@
<f:metadata> <f:metadata>
<f:viewAction action="#{dataViewController.onLoad()}" /> <f:viewAction action="#{dataViewController.onLoad()}" />
</f:metadata> </f:metadata>
<!-- Diese Form exportiert Ausgangsrechnungen nach Excel
-->
<ui:define name="scripts">
<script type="text/javascript">
/*<![CDATA[*/
$(document).ready(function () {
});
//ajax refresh...
function updateDataView(data, context) {
var viewBody = $("#dataview-controlls-id");
if (data.status === "begin") {
viewBody.addClass("loading");
} else if (data.status === "success") {
imixsOfficeMain.layoutAjaxEvent(data);
}
}
function handleSubmit(event) {
// remove ajax loader 5sec after trigger excel export
setTimeout(function () {
document.body.classList.remove('loading');
}, 5000);
}
/*]]>*/
</script>
</ui:define>
<ui:define name="content"> <ui:define name="content">
<f:view> <f:view>
<h:form id="dataview_id" pt:autocomplete="on"> <h:form id="dataview_id" pt:autocomplete="on" onsubmit="handleSubmit(event)">
<div class="imixs-form"> <div class="imixs-form">
<div class="imixs-header"> <div class="imixs-header">
<h1> <h1>
@ -50,14 +75,16 @@
<!-- Buttons --> <!-- Buttons -->
<div class="imixs-form-section"> <div id="dataview-controlls-id" class="imixs-form-section">
<div style="float:left;"> <div style="float:left;">
<h:commandButton value="Anzeigen" action="#{dataViewController.run()}"> <h:commandButton value="Anzeigen" action="#{dataViewController.run()}">
<f:ajax execute="@form dataview_result_id" render="dataview_result_id" <f:ajax execute="@form dataview_result_id" render="dataview_result_id"
onevent="updateDataView" /> onevent="updateDataView" />
</h:commandButton> </h:commandButton>
<h:commandButton value="Excel Export" action="#{dataViewController.run()}" /> <h:commandButton actionListener="#{dataViewController.export()}" value="Excel Export">
</h:commandButton>
<h:commandButton value="Close" action="/pages/notes?faces-redirect=true" /> <h:commandButton value="Close" action="/pages/notes?faces-redirect=true" />
</div> </div>
@ -133,10 +160,17 @@
<f:facet name="header">#{columnDef.item['item.label']}</f:facet> <f:facet name="header">#{columnDef.item['item.label']}</f:facet>
<h:outputText value="#{record.item[columnDef.item['item.name']]}"> <h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both" <f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePattern}" /> pattern="#{message.datePatternShort}" />
</h:outputText> </h:outputText>
</h:column>
<h:column rendered="#{columnDef.item['item.type'] eq 'xs:dateTime'}">
<f:facet name="header">#{columnDef.item['item.label']}</f:facet>
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePatternShort}" />
</h:outputText>
</h:column> </h:column>
</c:forEach> </c:forEach>
@ -146,30 +180,11 @@
</h:dataTable> </h:dataTable>
</div> </div>
</h:panelGroup> </h:panelGroup>
</div> </div>
</h:form> </h:form>
<!-- Init script -->
<script type="text/javascript">
/*<![CDATA[*/
$(document).ready(function () {
});
//ajax refresh...
function updateDataView(data, context) {
if (data.status === 'success') {
imixsOfficeMain.layoutAjaxEvent(data);
}
}
/*]]>*/
</script>
</f:view> </f:view>
</ui:define> </ui:define>