Skip to content

Commit c824c27

Browse files
committed
[KNOWAGE-9789] add total records field in PDF exported file (cockpit and dashboard)
1 parent 9b41a95 commit c824c27

2 files changed

Lines changed: 92 additions & 65 deletions

File tree

knowage-export/src/main/java/it/eng/knowage/engine/api/export/dashboard/pdf/DashboardPdfExporter.java

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ private void exportTableWidget(PDDocument document, JSONObject widget, String wi
168168
replaceWithThemeSettingsIfPresent(settings);
169169
columnStylesMap = getStylesMap(settings);
170170
initColumnWidths(columnsOrdered, columnStylesMap);
171-
buildFirstPageHeaders(table, settings, groupsAndColumnsMap, columnsOrdered, executionUser, font, extraValueLabel, extraValue, driversFromBody, parametersFromBody);
171+
buildFirstPageHeaders(table, settings, groupsAndColumnsMap, columnsOrdered, executionUser, totalNumberOfRows, font, extraValueLabel, extraValue, driversFromBody, parametersFromBody);
172172
}
173173

174174
rows = dataStore.getJSONArray("rows");
@@ -227,8 +227,8 @@ private void initColumnWidths(JSONArray columnsOrdered, Map<String, JSONArray> c
227227
}
228228
}
229229

230-
private void buildFirstPageHeaders(BaseTable table, JSONObject settings, Map<String, String> groupsAndColumnsMap, JSONArray columnsOrdered, String executionUser, PDFont font, String extraValueLabel, String extraValueField, JSONArray driversFromBody, JSONArray parametersFromBody) throws JSONException {
231-
createDocumentInformationRow(table, font, executionUser, extraValueLabel, extraValueField);
230+
private void buildFirstPageHeaders(BaseTable table, JSONObject settings, Map<String, String> groupsAndColumnsMap, JSONArray columnsOrdered, String executionUser, int totalNumberOfRows, PDFont font, String extraValueLabel, String extraValueField, JSONArray driversFromBody, JSONArray parametersFromBody) throws JSONException {
231+
createDocumentInformationRow(table, font, executionUser, totalNumberOfRows, extraValueLabel, extraValueField);
232232

233233
if (!groupsAndColumnsMap.isEmpty()) {
234234
Row<PDPage> groupHeaderRow = table.createRow(15f);
@@ -297,34 +297,38 @@ private void styleHeaderCell(JSONObject settings, Cell<PDPage> headerCell, PDFon
297297
}
298298
}
299299

300-
private void createDocumentInformationRow(BaseTable table, PDFont font, String executionUser, String extraValueLabel, String extraValue) {
300+
private void createDocumentInformationRow(BaseTable table, PDFont font, String executionUser, int totalNumberOfRows, String extraValueLabel, String extraValue) {
301301
try {
302302
String executionDateLabel = getExecutionDateLabel();
303303
String executionUserLabel = getExecutionUserLabel();
304+
String totalRecordsLabel = getTotalRecordsLabel();
304305

305306
PDPage page = table.getCurrentPage();
306307

307308
String executionDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
308309

309310
String line1 = executionDateLabel + executionDate;
310311
String line2 = executionUserLabel + executionUser;
311-
String line3 = null;
312+
String line3 = totalRecordsLabel + totalNumberOfRows;
312313
boolean isExtraValuePresent = extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty();
313-
if (isExtraValuePresent) {
314-
line3 = extraValueLabel + ": " + extraValue;
315-
}
314+
String line4 = isExtraValuePresent ? extraValueLabel + ": " + extraValue : null;
316315

317316
float fontSize = HEADER_FONT_SIZE;
318317
float leading = HEADER_LEADING;
319318

320319
float pageWidth = page.getMediaBox().getWidth();
320+
List<String> headerLines = new ArrayList<>();
321+
headerLines.add(line1);
322+
headerLines.add(line2);
323+
headerLines.add(line3);
324+
if (isExtraValuePresent) {
325+
headerLines.add(line4);
326+
}
321327

322-
float w1 = font.getStringWidth(line1) / 1000f * fontSize;
323-
float w2 = font.getStringWidth(line2) / 1000f * fontSize;
324-
325-
float w3 = isExtraValuePresent ? font.getStringWidth(line3) / 1000f * fontSize : 0;
326-
327-
float maxW = Math.max(w1, Math.max(w2, w3));
328+
float maxW = 0f;
329+
for (String headerLine : headerLines) {
330+
maxW = Math.max(maxW, font.getStringWidth(headerLine) / 1000f * fontSize);
331+
}
328332

329333
float x = pageWidth - HEADER_SIDE_MARGIN - maxW;
330334

@@ -337,12 +341,11 @@ private void createDocumentInformationRow(BaseTable table, PDFont font, String e
337341
contentStream.setFont(font, fontSize);
338342
contentStream.setNonStrokingColor(Color.BLACK);
339343
contentStream.newLineAtOffset(x, y);
340-
contentStream.showText(line1);
341-
contentStream.newLineAtOffset(0, -leading);
342-
contentStream.showText(line2);
343-
if (isExtraValuePresent) {
344-
contentStream.newLineAtOffset(0, -leading);
345-
contentStream.showText(line3);
344+
for (int i = 0; i < headerLines.size(); i++) {
345+
if (i > 0) {
346+
contentStream.newLineAtOffset(0, -leading);
347+
}
348+
contentStream.showText(headerLines.get(i));
346349
}
347350
contentStream.endText();
348351
}
@@ -578,8 +581,16 @@ private String getExecutionUserLabel() {
578581
};
579582
}
580583

584+
private String getTotalRecordsLabel() {
585+
return switch (getEffectiveLocale().getLanguage()) {
586+
case "it" -> "Numero totale di record: ";
587+
case "sk" -> "Celkový počet záznamov: ";
588+
default -> "Total Records: ";
589+
};
590+
}
591+
581592
private float calculateReservedTopHeightForDocumentInfo(String extraValueLabel, String extraValue) {
582-
int documentInfoLines = (extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty()) ? 3 : 2;
593+
int documentInfoLines = (extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty()) ? 4 : 3;
583594
return (documentInfoLines * HEADER_LEADING) + HEADER_BOTTOM_GAP;
584595
}
585596

knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/pdf/PdfExporter.java

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public class PdfExporter extends AbstractFormatExporter {
6262
private static final int DEFAULT_COLUMN_WIDTH = 150;
6363
private static final String KN_EXPORT_EXTRA_FIELD_LABEL = "kn-export-extra-field-label";
6464
private static final String KN_EXPORT_EXTRA_FIELD_VALUE = "kn-export-extra-field-value";
65+
private static final float HEADER_FONT_SIZE = 10f;
66+
private static final float HEADER_LEADING = 12f;
67+
private static final float HEADER_SIDE_MARGIN = 20f;
68+
private static final float HEADER_BOTTOM_GAP = 10f;
6569

6670

6771
private float totalColumnsWidth = 0;
@@ -131,12 +135,23 @@ private void exportTableWidget(PDDocument document, String templateString, long
131135
JSONArray jsonArray;
132136
URL resource = getClass().getClassLoader().getResource("/fonts/DejaVuSans.ttf");
133137
File pdfFontFile = new File(resource.toURI());
138+
String extraValueLabel = null;
139+
String extraValue = null;
140+
if (variables != null && variables.length() > 0) {
141+
extraValueLabel = variables.optString(KN_EXPORT_EXTRA_FIELD_LABEL);
142+
extraValue = variables.optString(KN_EXPORT_EXTRA_FIELD_VALUE);
143+
}
144+
float reservedTopHeight = calculateReservedTopHeightForDocumentInfo(extraValueLabel, extraValue);
134145
do {
135146
dataStore = this.getDataStoreForWidget(template, widget, offset, fetchSize);
136147

148+
if (offset == 0) {
149+
totalNumberOfRows = dataStore.getInt("results");
150+
}
151+
137152
PDPage newPage = createPage(settings, widget);
138153
document.addPage(newPage);
139-
table = createBaseTable(document, newPage);
154+
table = createBaseTable(document, newPage, reservedTopHeight);
140155

141156
JSONObject widgetData = dataStore.getJSONObject("widgetData");
142157
JSONObject widgetContent = widgetData.getJSONObject("content");
@@ -159,23 +174,14 @@ private void exportTableWidget(PDDocument document, String templateString, long
159174
columnStyles = getColumnsStyles(columnsOrdered, widgetContent);
160175
initColumnWidths(columnStyles, columnsOrdered.length(), pdfHiddenColumns);
161176

162-
totalNumberOfRows = dataStore.getInt("results");
163-
164177
}
165178

166179
rows = dataStore.getJSONArray("rows");
167180

168181
PDFont font = PDType0Font.load(table.document, pdfFontFile);
169182

170-
String extraValueLabel = null;
171-
String extraValue = null;
172-
if (variables != null && variables.length() > 0) {
173-
extraValueLabel = variables.optString(KN_EXPORT_EXTRA_FIELD_LABEL);
174-
extraValue = variables.optString(KN_EXPORT_EXTRA_FIELD_VALUE);
175-
}
176-
177183
addDataToTable(table, settings, columnsOrdered, pdfHiddenColumns, columnDateFormats, columnStyles,
178-
rows, font, style, widgetData, widgetContent, creationUser, extraValueLabel, extraValue);
184+
rows, font, style, widgetData, widgetContent, creationUser, totalNumberOfRows, extraValueLabel, extraValue);
179185

180186
offset += fetchSize;
181187

@@ -194,10 +200,10 @@ private void exportTableWidget(PDDocument document, String templateString, long
194200
}
195201

196202
private void addDataToTable(BaseTable table, JSONObject settings, JSONArray columnsOrdered,
197-
List<Integer> pdfHiddenColumns, String[] columnDateFormats, JSONObject[] columnStyles, JSONArray rows, PDFont font, JSONObject style, JSONObject widgetData, JSONObject widgetContent, String creationUser, String extraValueLabel, String extraValue)
203+
List<Integer> pdfHiddenColumns, String[] columnDateFormats, JSONObject[] columnStyles, JSONArray rows, PDFont font, JSONObject style, JSONObject widgetData, JSONObject widgetContent, String creationUser, int totalNumberOfRows, String extraValueLabel, String extraValue)
198204
throws JSONException {
199205

200-
addHeaderToTable(table, style, widgetData, widgetContent, columnsOrdered, pdfHiddenColumns, font, creationUser, extraValueLabel, extraValue);
206+
addHeaderToTable(table, style, widgetData, widgetContent, columnsOrdered, pdfHiddenColumns, font, creationUser, totalNumberOfRows, extraValueLabel, extraValue);
201207

202208
// Check if summary row is enabled
203209
boolean summaryRowEnabled = false;
@@ -307,11 +313,11 @@ private void addDataToTable(BaseTable table, JSONObject settings, JSONArray colu
307313
}
308314

309315
private void addHeaderToTable(BaseTable table, JSONObject style, JSONObject widgetData, JSONObject widgetContent,
310-
JSONArray columnsOrdered, List<Integer> pdfHiddenColumns, PDFont font, String creationUser, String extraValueLabel, String extraValueField) throws JSONException {
316+
JSONArray columnsOrdered, List<Integer> pdfHiddenColumns, PDFont font, String creationUser, int totalNumberOfRows, String extraValueLabel, String extraValueField) throws JSONException {
311317
JSONArray groupsFromWidgetContent = getGroupsFromWidgetContent(widgetData);
312318
Map<String, String> groupsAndColumnsMap = getGroupAndColumnsMap(widgetContent, groupsFromWidgetContent);
313319

314-
createDocumentInformationRow(table, font, creationUser, extraValueLabel, extraValueField);
320+
createDocumentInformationRow(table, font, creationUser, totalNumberOfRows, extraValueLabel, extraValueField);
315321

316322
if (!groupsAndColumnsMap.isEmpty()) {
317323
Row<PDPage> groupHeaderRow = table.createRow(15f);
@@ -736,20 +742,24 @@ private static String extractParameterName(String parameterKey) {
736742
return parameterKey;
737743
}
738744

739-
private void createDocumentInformationRow(BaseTable table, PDFont font, String creationUser, String extraValueLabel, String extraValue) {
745+
private void createDocumentInformationRow(BaseTable table, PDFont font, String creationUser, int totalNumberOfRows, String extraValueLabel, String extraValue) {
740746
try {
741747
String executionDateLabel;
742748
String creationUserLabel;
749+
String totalRecordsLabel;
743750

744751
if (getLocale().toString().equals("sk_SK")) {
745752
executionDateLabel = "Dátum vytvorenia: ";
746753
creationUserLabel = "Vytvoril: ";
754+
totalRecordsLabel = "Celkový počet záznamov: ";
747755
} else if (getLocale().toString().equals("it_IT")) {
748756
executionDateLabel = "Data di esecuzione: ";
749757
creationUserLabel = "Utente di esecuzione: ";
758+
totalRecordsLabel = "Numero totale di record: ";
750759
} else {
751760
executionDateLabel = "Execution User: ";
752761
creationUserLabel = "Creation User: ";
762+
totalRecordsLabel = "Total Records: ";
753763
}
754764

755765
PDPage page = table.getCurrentPage();
@@ -758,33 +768,30 @@ private void createDocumentInformationRow(BaseTable table, PDFont font, String c
758768

759769
String line1 = executionDateLabel + executionDate;
760770
String line2 = creationUserLabel + creationUser;
761-
String line3 = null;
762-
if (extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty()) {
763-
line3 = extraValueLabel + ": " + extraValue;
764-
}
771+
String line3 = totalRecordsLabel + totalNumberOfRows;
772+
boolean isExtraValuePresent = extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty();
773+
String line4 = isExtraValuePresent ? extraValueLabel + ": " + extraValue : null;
765774

766-
float fontSize = 10f;
767-
float leading = 12f;
768-
float margin = 20f;
775+
float fontSize = HEADER_FONT_SIZE;
776+
float leading = HEADER_LEADING;
769777

770778
float pageWidth = page.getMediaBox().getWidth();
771-
float pageHeight = page.getMediaBox().getHeight();
772-
773-
float w1 = font.getStringWidth(line1) / 1000f * fontSize;
774-
float w2 = font.getStringWidth(line2) / 1000f * fontSize;
775-
float w3;
776-
if (line3 != null) {
777-
w3 = font.getStringWidth(line3) / 1000f * fontSize;
778-
w2 = Math.max(w2, w3);
779+
List<String> headerLines = new ArrayList<>();
780+
headerLines.add(line1);
781+
headerLines.add(line2);
782+
headerLines.add(line3);
783+
if (isExtraValuePresent) {
784+
headerLines.add(line4);
779785
}
780-
float maxW = Math.max(w1, w2);
781786

782-
float x = pageWidth - margin - maxW;
787+
float maxW = 0f;
788+
for (String headerLine : headerLines) {
789+
maxW = Math.max(maxW, font.getStringWidth(headerLine) / 1000f * fontSize);
790+
}
783791

784-
float yStartNewPage = pageHeight - (2 * margin);
792+
float x = pageWidth - HEADER_SIDE_MARGIN - maxW;
785793

786-
float additionalGap = 12f;
787-
float y = yStartNewPage + additionalGap + leading;
794+
float y = getHeaderStartY(page);
788795

789796
try (org.apache.pdfbox.pdmodel.PDPageContentStream contentStream =
790797
new org.apache.pdfbox.pdmodel.PDPageContentStream(table.document, page, org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode.APPEND, true)) {
@@ -793,12 +800,11 @@ private void createDocumentInformationRow(BaseTable table, PDFont font, String c
793800
contentStream.setFont(font, fontSize);
794801
contentStream.setNonStrokingColor(Color.BLACK);
795802
contentStream.newLineAtOffset(x, y);
796-
contentStream.showText(line1);
797-
contentStream.newLineAtOffset(0, -leading);
798-
contentStream.showText(line2);
799-
if (line3 != null) {
800-
contentStream.newLineAtOffset(0, -leading);
801-
contentStream.showText(line3);
803+
for (int i = 0; i < headerLines.size(); i++) {
804+
if (i > 0) {
805+
contentStream.newLineAtOffset(0, -leading);
806+
}
807+
contentStream.showText(headerLines.get(i));
802808
}
803809
contentStream.endText();
804810

@@ -808,6 +814,15 @@ private void createDocumentInformationRow(BaseTable table, PDFont font, String c
808814
}
809815
}
810816

817+
private float calculateReservedTopHeightForDocumentInfo(String extraValueLabel, String extraValue) {
818+
int documentInfoLines = (extraValueLabel != null && !extraValueLabel.isEmpty() && extraValue != null && !extraValue.isEmpty()) ? 4 : 3;
819+
return (documentInfoLines * HEADER_LEADING) + HEADER_BOTTOM_GAP;
820+
}
821+
822+
private float getHeaderStartY(PDPage page) {
823+
return page.getMediaBox().getHeight() - HEADER_SIDE_MARGIN + 4f;
824+
}
825+
811826
private int getAdjacentEqualNamesAmount(Map<String, String> groupsAndColumnsMap, JSONArray columnsOrdered, int matchStartIndex, String groupNameToMatch) {
812827
try {
813828
int adjacents = 0;
@@ -1071,7 +1086,7 @@ private PDRectangle calculateTableDimensions(JSONObject widgetConf) {
10711086
}
10721087
}
10731088

1074-
private BaseTable createBaseTable(PDDocument doc, PDPage page) {
1089+
private BaseTable createBaseTable(PDDocument doc, PDPage page, float reservedTopHeight) {
10751090
try {
10761091
float margin = 20;
10771092
// starting y position is whole page height subtracted by top and bottom margin
@@ -1080,7 +1095,8 @@ private BaseTable createBaseTable(PDDocument doc, PDPage page) {
10801095
float tableWidth = page.getMediaBox().getWidth() - (2 * margin);
10811096
// y position is your coordinate of top left corner of the table
10821097
Assert.assertTrue(tableWidth > 0, "Page dimension is too small!");
1083-
float yPosition = 550;
1098+
float computedYPosition = Math.min(550, getHeaderStartY(page) - reservedTopHeight);
1099+
float yPosition = Math.max(bottomMargin + HEADER_BOTTOM_GAP, computedYPosition);
10841100
return new BaseTable(yPosition, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true);
10851101
} catch (Exception e) {
10861102
throw new SpagoBIRuntimeException("Cannot create PDF Base Table object:", e);

0 commit comments

Comments
 (0)