Excel Export Funktion
This commit is contained in:
parent
d99aad1322
commit
2c6636bfbc
3 changed files with 120 additions and 58 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
package com.alexanderlogistics.mahnlauf;
|
package com.alexanderlogistics.mahnlauf;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
@ -9,8 +12,16 @@ import java.time.ZoneId;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.CellCopyPolicy;
|
||||||
|
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.archive.core.SnapshotService;
|
import org.imixs.archive.core.SnapshotService;
|
||||||
import org.imixs.workflow.FileData;
|
import org.imixs.workflow.FileData;
|
||||||
import org.imixs.workflow.ItemCollection;
|
import org.imixs.workflow.ItemCollection;
|
||||||
|
|
@ -21,6 +32,8 @@ import org.imixs.workflow.faces.data.DocumentController;
|
||||||
import org.imixs.workflow.faces.data.WorkflowController;
|
import org.imixs.workflow.faces.data.WorkflowController;
|
||||||
import org.imixs.workflow.office.forms.CustomFormItem;
|
import org.imixs.workflow.office.forms.CustomFormItem;
|
||||||
|
|
||||||
|
import com.alexanderlogistics.ZahlungsavisExportAdapter;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.enterprise.context.ConversationScoped;
|
import jakarta.enterprise.context.ConversationScoped;
|
||||||
import jakarta.faces.context.ExternalContext;
|
import jakarta.faces.context.ExternalContext;
|
||||||
|
|
@ -47,6 +60,7 @@ public class ExcelExportController implements Serializable {
|
||||||
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
||||||
final String TYPE_TEXTBLOCK = "textblock";
|
final String TYPE_TEXTBLOCK = "textblock";
|
||||||
|
|
||||||
|
public static final int MAX_ROWS = 3000;
|
||||||
@Inject
|
@Inject
|
||||||
protected DocumentService documentService;
|
protected DocumentService documentService;
|
||||||
|
|
||||||
|
|
@ -86,10 +100,8 @@ public class ExcelExportController implements Serializable {
|
||||||
public String export() throws PluginException {
|
public String export() throws PluginException {
|
||||||
|
|
||||||
logger.info("start export....");
|
logger.info("start export....");
|
||||||
|
|
||||||
Date start = filter.getItemValueDate("start");
|
Date start = filter.getItemValueDate("start");
|
||||||
Date stop = filter.getItemValueDate("stop");
|
Date stop = filter.getItemValueDate("stop");
|
||||||
|
|
||||||
logger.info("...daterange=" + start + " - " + stop);
|
logger.info("...daterange=" + start + " - " + stop);
|
||||||
|
|
||||||
// serach date range?
|
// serach date range?
|
||||||
|
|
@ -123,11 +135,13 @@ public class ExcelExportController implements Serializable {
|
||||||
if (!filter.getItemValueString("space.name").isEmpty()) {
|
if (!filter.getItemValueString("space.name").isEmpty()) {
|
||||||
query += " AND (space.name:" + filter.getItemValueString("space.name") + ")";
|
query += " AND (space.name:" + filter.getItemValueString("space.name") + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workflowController.getWorkitem() != null
|
if (workflowController.getWorkitem() != null
|
||||||
&& !workflowController.getWorkitem().getItemValueString("dbtr.number").isEmpty()) {
|
&& !workflowController.getWorkitem().getItemValueString("dbtr.number").isEmpty()) {
|
||||||
query += " AND (dbtr.number:" + workflowController.getWorkitem().getItemValueString("dbtr.number") + ")";
|
query += " AND (dbtr.number:" + workflowController.getWorkitem().getItemValueString("dbtr.number") + ")";
|
||||||
}
|
}
|
||||||
|
if (!filter.getItemValueString("invoice.text").isEmpty()) {
|
||||||
|
query += " AND (invoice.positions:" + filter.getItemValueString("invoice.text") + ")";
|
||||||
|
}
|
||||||
|
|
||||||
// load the text block
|
// load the text block
|
||||||
String template = "ausgangsrechnungen-export_template.xlsx";
|
String template = "ausgangsrechnungen-export_template.xlsx";
|
||||||
|
|
@ -139,13 +153,17 @@ public class ExcelExportController implements Serializable {
|
||||||
"Missing Excel Export Template - template=" + template + " not found!");
|
"Missing Excel Export Template - template=" + template + " not found!");
|
||||||
}
|
}
|
||||||
String targetName = "ausgangsrechnungen-export_" + dateformat.format(new Date()) + ".xlsx";
|
String targetName = "ausgangsrechnungen-export_" + dateformat.format(new Date()) + ".xlsx";
|
||||||
fileData.setName(targetName);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
List<ItemCollection> invoices = documentService.find(query, MAX_ROWS, 0);
|
||||||
|
if (invoices.size() > 0) {
|
||||||
|
insertInvoiceRows(invoices, fileData);
|
||||||
|
}
|
||||||
|
fileData.setName(targetName);
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://stackoverflow.com/questions/9391838/how-to-provide-a-file-download-from-a-jsf-backing-bean
|
// https://stackoverflow.com/questions/9391838/how-to-provide-a-file-download-from-a-jsf-backing-bean
|
||||||
download(fileData);
|
download(fileData);
|
||||||
} catch (IOException e) {
|
} catch (IOException | QueryException e) {
|
||||||
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
|
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
|
||||||
"Failed to generate Excel Export: " + e.getMessage());
|
"Failed to generate Excel Export: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
@ -229,10 +247,6 @@ public class ExcelExportController implements Serializable {
|
||||||
// debtr item
|
// debtr item
|
||||||
dbtrItem = new CustomFormItem("dbtr.number", "text", "", false, false, false, "", null, false, 0);
|
dbtrItem = new CustomFormItem("dbtr.number", "text", "", false, false, false, "", null, false, 0);
|
||||||
|
|
||||||
// public CustomFormItem(String name, String type, String label, boolean
|
|
||||||
// required, boolean readonly, boolean disabled,
|
|
||||||
// String options,
|
|
||||||
// String path, boolean hide, int span) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomFormItem getItem() {
|
public CustomFormItem getItem() {
|
||||||
|
|
@ -240,4 +254,91 @@ public class ExcelExportController implements Serializable {
|
||||||
return dbtrItem;
|
return dbtrItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This helper method inserts a row for each invoice
|
||||||
|
*
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
private void insertInvoiceRows(List<ItemCollection> invoices, 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);
|
||||||
|
|
||||||
|
XSSFCell standCell = getCellByRef(doc, sheet, "F6");
|
||||||
|
standCell.setCellValue(new Date());
|
||||||
|
|
||||||
|
CellReference cr = new CellReference("A11");
|
||||||
|
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, invoices.size(), true, true);
|
||||||
|
|
||||||
|
for (ItemCollection invoice : invoices) {
|
||||||
|
logger.finest("......copy row...");
|
||||||
|
|
||||||
|
// now create a new line..
|
||||||
|
XSSFRow row = sheet.createRow(rowPos);
|
||||||
|
row.copyRowFrom(referenceRow, new CellCopyPolicy());
|
||||||
|
// insert values
|
||||||
|
row.getCell(0).setCellValue(invoice.getItemValueString("invoice.number"));
|
||||||
|
row.getCell(1).setCellValue(invoice.getItemValueString("dbtr.number"));
|
||||||
|
row.getCell(2).setCellValue(invoice.getItemValueString("invoice.text"));
|
||||||
|
|
||||||
|
row.getCell(3).setCellValue(invoice.getItemValueDate("invoice.date"));
|
||||||
|
row.getCell(4).setCellValue(invoice.getItemValueDate("invoice.duedate"));
|
||||||
|
|
||||||
|
row.getCell(5).setCellValue(invoice.getItemValueDouble("invoice.total"));
|
||||||
|
|
||||||
|
rowPos++;
|
||||||
|
}
|
||||||
|
// delete reference row
|
||||||
|
sheet.shiftRows(referenceRowPos, lastRow + invoices.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(ZahlungsavisExportAdapter.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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,40 +7,30 @@
|
||||||
|
|
||||||
<!-- Diese Form exportiert Ausgangsrechnungen nach Excel
|
<!-- Diese Form exportiert Ausgangsrechnungen nach Excel
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<ui:define name="scripts">
|
<ui:define name="scripts">
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
|
function handleSubmit(event) {
|
||||||
$(document).ready(function () {
|
// remove ajax kringel
|
||||||
|
setTimeout(function() {
|
||||||
});
|
document.body.classList.remove('loading');
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
</script>
|
</script>
|
||||||
</ui:define>
|
</ui:define>
|
||||||
|
|
||||||
<ui:define name="content">
|
<ui:define name="content">
|
||||||
<f:view>
|
<f:view>
|
||||||
|
<h:form id="import_form_id" onsubmit="handleSubmit(event)">
|
||||||
<h:form id="import_form_id">
|
|
||||||
<!-- ########## Error ########## -->
|
<!-- ########## Error ########## -->
|
||||||
<ui:include src="/error_message.xhtml" />
|
<ui:include src="/error_message.xhtml" />
|
||||||
|
|
||||||
<div class="imixs-form">
|
<div class="imixs-form">
|
||||||
<div class="imixs-header">
|
<div class="imixs-header">
|
||||||
<h1>Excle Export Ausgangsrechnungen</h1>
|
<h1>Excle Export Ausgangsrechnungen</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<h:panelGroup layout="block" styleClass="imixs-body" id="analyse_panel">
|
<h:panelGroup layout="block" styleClass="imixs-body" id="analyse_panel">
|
||||||
|
|
||||||
<div class="imixs-form-panel">
|
<div class="imixs-form-panel">
|
||||||
|
|
||||||
|
|
||||||
<div class="ui-state-highlight ui-corner-all" style="margin-bottom: 10px; padding: .5em;">
|
<div class="ui-state-highlight ui-corner-all" style="margin-bottom: 10px; padding: .5em;">
|
||||||
<p>Der folgende Report exportiert <i>Ausgangsrechnungen</i>, in eine Excel Datei. Der Export ist auf maximal 3000 Einträge pro Tabelle beschränkt
|
<p>Der folgende Report exportiert <i>Ausgangsrechnungen</i>, in eine Excel Datei. Der Export ist auf maximal 3000 Einträge pro Tabelle beschränkt
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -56,12 +46,8 @@
|
||||||
<f:convertDateTime pattern="#{message.datePatternShort}"
|
<f:convertDateTime pattern="#{message.datePatternShort}"
|
||||||
timeZone="#{message.timeZone}" />
|
timeZone="#{message.timeZone}" />
|
||||||
</h:inputText>
|
</h:inputText>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
Bis:<span class="imixs-required">*</span>
|
Bis:<span class="imixs-required">*</span>
|
||||||
|
|
@ -74,9 +60,6 @@
|
||||||
</h:inputText>
|
</h:inputText>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
Abteilung:
|
Abteilung:
|
||||||
|
|
@ -88,7 +71,6 @@
|
||||||
</h:inputText>
|
</h:inputText>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
Debitor:
|
Debitor:
|
||||||
|
|
@ -101,48 +83,27 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
Positionsnummer:
|
Positionsnummer:
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<h:inputText
|
<h:inputText
|
||||||
value="#{excelExportController.filter.item['invoice.text']}">
|
value="#{excelExportController.filter.item['invoice.text']}">
|
||||||
|
|
||||||
</h:inputText>
|
</h:inputText>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
x <h:commandButton actionListener="#{excelExportController.export()}" immediate="true"
|
<h:commandButton actionListener="#{excelExportController.export()}"
|
||||||
action="/pages/admin/excel_export_rechnungsausgang.jsf?faces-redirect=true"
|
|
||||||
value="Excel Export starten">
|
value="Excel Export starten">
|
||||||
|
|
||||||
</h:commandButton>
|
</h:commandButton>
|
||||||
<h:commandButton value="#{message.close}" action="notes" />
|
<h:commandButton value="#{message.close}" action="notes" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</h:panelGroup>
|
</h:panelGroup>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="imixs-footer"></div>
|
<div class="imixs-footer"></div>
|
||||||
</h:form>
|
</h:form>
|
||||||
</f:view>
|
</f:view>
|
||||||
</ui:define>
|
</ui:define>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ui:composition>
|
</ui:composition>
|
||||||
Binary file not shown.
Loading…
Reference in a new issue