简体   繁体   English

如何从同一行显示的Excel文件中显示两个不同大小的数组以输出PDF?

[英]How to display two arrays of different sizes from an Excel file displayed on same line for PDF output?

I have an Excel file I'm reading in with Apache POI and getting headers, rows & cell data which I'm storing in two arrays. 我有一个要用Apache POI读取的Excel文件,并获取要存储在两个数组中的标头,行和单元格数据。 I am using PDF box and am trying to display all of the headers vertically with the corresponding row data. 我正在使用PDF框,并尝试垂直显示所有标题以及相应的行数据。

For example: the header row contains name, email, date of birth, salary and department followed by three rows of data. 例如:标题行包含姓名,电子邮件,出生日期,薪水和部门,后跟三行数据。 Each row of data should produce its own PDF document listing the labels and values vertically down the page but for now I'm only trying to list all the values in one PDF document. 每一行数据都应产生自己的PDF文档,该文档在页面的垂直下方列出标签和值,但现在我仅尝试列出一个PDF文档中的所有值。

  • Name: Joe Smith 姓名:乔·史密斯
  • Email: js@something.com 电子邮件:js@something.com
  • Date of Birth: 05/06/1976 生日:1976/05/06
  • Salary: $100,000.00 薪酬:$ 100,000.00
  • Department: Sales 部门:销售部

The problem I'm having is only the last record in my Excel sheet is printing to the PDF and the headers are mismatching the corresponding row and cell data. 我遇到的问题只是Excel工作表中的最后一条记录正在打印为PDF,并且标题与相应的行和单元格数据不匹配。 I believe this is due to the mismatch in the count of 5 elements in the header array and 15 elements in the cell array. 我相信这是由于标头数组中的5个元素和单元格数组中的15个元素的计数不匹配所致。

Below are some snippets of what I'm doing to produce this along with a screen shot of both my Excel file layout and the PDF that's being generated. 以下是我为实现此目的所做的一些摘要,以及我的Excel文件布局和正在生成的PDF的屏幕截图。

My Excel Sheet (right click to open not sure why it isn't linking to full size pics below) 我的Excel工作表(右键打开无法确定为什么未链接到下面的原图)

屏幕截图

屏幕截图2

屏幕截图3

//Hold header values in Array
List<String> headerValues = new ArrayList<>();

//Hold cell values in Array
List<String> cellValues = new ArrayList<>();

for(int i = 0; i < headerValues.size() && i < cellValues.size(); i++){
    cont.showText(headerValues.get(i) + cellValues.get(i));
    cont.newLine();
}

Here was another way I had done this which produced the same result as the for loop 这是我执行此操作的另一种方式,产生的结果与for循环相同

Iterator<String> h = headerValues.iterator();
Iterator<String> c = cellValues.iterator();

while(h.hasNext() && c.hasNext()){
    cont.showText(h.next() +":" + c.next());
    cont.newLine();
}

The result I'm trying to get to is print each of the header values in my excel spreadsheet vertically for each row's data in my Excel Sheet. 我想要得到的结果是在Excel电子表格中垂直打印Excel工作表中每行数据的每个标题值。

Your collection structure is not optimal. 您的集合结构不是最佳的。 At least your cell values should not be all in one list. 至少您的单元格值不应全部包含在一个列表中。 The data structure of an default Excel table is like a database table. 默认Excel表的数据结构类似于数据库表。 There are data records (the rows) which consists of fields (the column headers). 存在由字段(列标题)组成的数据记录(行)。 So your cell values should be in a List<List<String>> dataRecords . 因此,您的单元格值应位于List<List<String>> dataRecords There the main List is a list of rows and the inner List is the list of fields in the rows. 在这里,主List是行的列表,内部List是行中的字段的列表。

The column headers might be a List<String> colHeaders but the better structure would be a TreeMap<Integer, String> colHeaders where the Integer key is the column index in the Excel sheet. 列标题可以是List<String> colHeaders但更好的结构是TreeMap<Integer, String> colHeaders ,其中Integer键是Excel表中的列索引。 Using that it is clear what Excel columns in the sheet really contain the data fields. 使用它可以清楚地知道工作表中的哪些Excel列真正包含数据字段。

Let's have a complete example: 让我们举一个完整的例子:

import java.io.FileInputStream;

import org.apache.poi.ss.usermodel.*;

import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.*;
import org.apache.pdfbox.pdmodel.common.*;

import java.util.Map;
import java.util.TreeMap;
import java.util.List;
import java.util.ArrayList;

class GetDataFromExcel {

 public static void main(String[] args) throws Exception {

  Workbook workbook = WorkbookFactory.create(new FileInputStream("ExcelExample.xlsx"));

  DataFormatter dataFormatter = new DataFormatter();
  FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();

  Sheet sheet = workbook.getSheetAt(0);

  int headerRowNum = sheet.getFirstRowNum();

  // collecting the column headers
  TreeMap<Integer, String> colHeaders = new TreeMap<Integer, String>();
  Row row = sheet.getRow(headerRowNum);
  for (Cell cell : row) {
   int colIdx = cell.getColumnIndex();
   String value = dataFormatter.formatCellValue(cell, formulaEvaluator);
   colHeaders.put(colIdx, value);
  }

System.out.println(colHeaders);

  // collecting the data records
  List<List<String>> dataRecords = new ArrayList<List<String>>();
  for (int r = headerRowNum + 1; r <= sheet.getLastRowNum(); r++) {
   row = sheet.getRow(r); if (row == null) row = sheet.createRow(r);
   List<String> values = new ArrayList<String>();
   for (Map.Entry<Integer, String> entry : colHeaders.entrySet()) {
    int colIdx = entry.getKey();
    Cell cell = row.getCell(colIdx); if (cell == null) cell = row.createCell(colIdx);
    String value = dataFormatter.formatCellValue(cell, formulaEvaluator);
    values.add(value);
   }
   dataRecords.add(values);
  }

System.out.println(dataRecords);

  workbook.close();

  // create PDF
  final PDFont font = PDType1Font.HELVETICA;
  final float fontSize = 12.0f;
  final float lineHeight = fontSize * 1.42857f;
  PDPage page = new PDPage(); //U.S. Letter, 8.5" x 11"
  final PDRectangle artBox = page.getArtBox();
  final float artBoxHeight = artBox.getHeight();
  final float artBoxWidth = artBox.getWidth();
  final float leftMargin = artBoxWidth / 8.5f; // 1"
  final float topMargin = artBoxHeight / 11.0f; // 1"
  final float bottomMargin = artBoxHeight / 11.0f; // 1"

  PDDocument doc = new PDDocument();

  doc.addPage(page);
  PDPageContentStream contents = new PDPageContentStream(doc, page);
  contents.beginText();
  contents.setFont(font, fontSize);
  float currentLinePos = artBoxHeight-topMargin;
  contents.newLineAtOffset(leftMargin, currentLinePos);

  for (List<String> dataRecord : dataRecords) {
   Integer colIdx = colHeaders.firstKey();
   for (String value : dataRecord) {
    if (colIdx != null) {
     String header = colHeaders.get(colIdx);
     if (currentLinePos <= bottomMargin) {
      contents.endText();
      contents.close();
      page = new PDPage();
      doc.addPage(page);
      contents = new PDPageContentStream(doc, page);
      contents.beginText();
      contents.setFont(font, fontSize);
      currentLinePos = artBoxHeight-topMargin;
      contents.newLineAtOffset(leftMargin, currentLinePos);
     }
     contents.showText(header + ": " + value);
     contents.newLineAtOffset(0, -lineHeight);
     currentLinePos -= lineHeight;
    }
    colIdx = colHeaders.higherKey(colIdx);
   }
   contents.newLineAtOffset(0, -lineHeight);
   currentLinePos -= lineHeight;   
  }

  contents.endText();
  contents.close();

  doc.save("ExcelExample.pdf");
  doc.close();

 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM