[英]PdfBox issue while changing page
我不是問這類問題的忠實擁護者,但是,嘗試解決我的代碼中的這個錯誤已經整整三天了。
我知道這是一個邏輯問題,我知道如何解決這個問題,但是當涉及到將我的想法轉化為代碼時,我只是無法使其按需工作。
我正在研究合同背書(合同的修改),該書將比較2個表中的數據,如果其中任何一個已更改,則僅繪制該信息。
有時,諸如條件之類的變化信息的長度會增加或減少,這就是問題所在。
我制定了一種算法,一旦完成繪制信息,它將獲得最小的Y坐標,但是當我更改頁面Y坐標時,必須將其重置為700f
並從此處重新開始繪制。
我使用的代碼最初是由另一個不在這里的程序員制作的,我不知道如何用PDF編寫MCVE 。
但是以下是我認為可以幫助您的方法。
我如何比較和繪制PDF上的信息的示例:
sOffA
和sOffE
是從一個名為Class對象SubscriptionOffer
和A
代表Agreement
而E
的Endorsement
。 認可是MySQL上的表Agreement
的副本,但信息已修改。 可能這是無關的信息,也許不是。
if (!nullOrEmpty(sOffA.getGeneralConditions()) &&
!nullOrEmpty(sOffE.getGeneralConditions())) {
if (!getStringValue(sOffA.getGeneralConditions()).
equals(getStringValue(sOffE.getGeneralConditions()))) {
minYs[0] = pdf.rText(LEFT_MARGIN, y, 10,
constants.generalConditions(),
getStringValue(sOffA.
getGeneralConditions()));
minYs[1] = pdf.rText(HALF_PAGE, y, 10,
constants.generalConditions(),
getStringValue(sOffE.
getGeneralConditions()));
y = checkY(pdf, minYs);
}
} else if (nullOrEmpty(sOffA.getGeneralConditions()) &&
!nullOrEmpty(sOffE.getGeneralConditions())) {
minYs[0] = pdf.rText(LEFT_MARGIN, y, 10, "", "");
minYs[1] = pdf.rText(HALF_PAGE, y, 10,
constants.generalConditions(),
getStringValue(sOffE.
getGeneralConditions()));
y = checkY(pdf, minYs);
} else if (!nullOrEmpty(sOffA.getGeneralConditions()) &&
nullOrEmpty(sOffE.getGeneralConditions())) {
minYs[0] = pdf.rText(LEFT_MARGIN, y, 10,
constants.generalConditions(),
getStringValue(sOffA.
getGeneralConditions()));
minYs[1] = pdf.rText(HALF_PAGE, y, 10, "", "");
y = checkY(pdf, minYs);
}
我使用的數組是這個數組:
private float[] minYs = new float[] {700, 700, 700, 700, 700, 700, 700,
700, 700};
這是方法checkY
,它檢查數組中的哪個Y(如上所示)是最小的Y,然后針對所有元素將整個數組重新啟動回700f。 然后檢查最低Y坐標下方的空間是否足以繪制下一個項目。
private float checkY(PdfRenderingEndorsement pdf, float... ys) throws Exception {
float y2 = getMinY(pdf, ys);
for (int i = 0; i < ys.length; i++) {
ys[i] = 700;
}
y2 = pdf.checkContentStream(y2, 5, 10);
return y2;
}
這種方法是我猜想我的邏輯問題所在的地方,並且您可以看到我嘗試了不同的事情,原始算法只是for-each
部分,然后我嘗試了沒有成功的其他事情。
private float getMinY(PdfRenderingEndorsement pdf, float... ys) {
float result = 700f;
float lowest1 = 0, lowest2 = 0;
for (int i = 0; i < ys.length; i++) {
for (int j = 0; j < ys.length; j++) {
if (ys[j] > ys[i]) {
float aux = ys[i];
ys[i] = ys[j];
ys[j] = aux;
//lowest1 = ys[i];
//lowest2 = ys[j];
}
}
}
if (ys.length > 1) {
lowest1 = ys[0];
lowest2 = ys[1];
}
LOGGER.trace("lowest1: " + lowest1);
LOGGER.trace("lowest2: " + lowest2);
LOGGER.trace("newPage " + pdf.getNewPage());
/*if(pdf.getNewPage()) {
return lowest1 > lowest2 ? lowest2 : lowest1;
}
*/
/*for (float y : ys) {
if (y < result) {
result = y;
}
}*/
return lowest1 > lowest2 && pdf.getNewPage() ? lowest1 : lowest2;
//return lowest1;
}
我獲取對象的String值並檢查它們是否為null或為空的方法:
private boolean nullOrEmpty(String s) {
return s == null || s.isEmpty();
}
private String getStringValue(Object o) {
if (o == null) {
return "";
}
return getStringValue(o, null);
}
private String getStringValue(Object o, Class< ? extends Unit> clazz) {
if (o instanceof Boolean) {
Boolean bd = (Boolean) o;
if (bd) {
return constants.getString("dbeditorYes");
} else {
return constants.getString("dbeditorNo");
}
} else if (o instanceof Date) {
Date date = (Date) o;
DateFormat df = new SimpleDateFormat(DateConstants.DATE_FORMAT);
return df.format(date);
} else if (o instanceof Enum) {
Enum en = (Enum) o;
return constants.enumMap().get(en.toString());
} else if (o instanceof Integer) {
Integer integer = (Integer) o;
if (clazz == null) {
return String.valueOf(integer);
} else {
Unit entry = unitSvc.get(clazz, integer);
String[] params = entry.toString().split("\\|");
String label = params.length == 1 ? params[0] : params[1];
return label;
}
} else if (o instanceof BigDecimal) {
BigDecimal bd = (BigDecimal) o;
DecimalFormat df = new DecimalFormat("#,##0");
df = new DecimalFormat("#,##0.00");
return df.format(bd);
} else if (o instanceof Float) {
Float bd = (Float) o;
DecimalFormat df = new DecimalFormat("#,##0");
df = new DecimalFormat("#,##0.00");
return df.format(bd);
} else if (o instanceof String) {
String td = (String) o;
return td;
}
return "";
}
以上所有方法均對應於PdfEndorsement
類。
這是PdfRenderingEndorsement
類,它是實際繪制數據的類(由於使用了所有方法,因此是完整的類):
public class PdfRenderingEndorsement {
private static final Logger LOGGER = Logger.
getLogger(PdfRenderingEndorsement.class);
private static final float BOTTOM_MARGIN = 60;
private static final int DESC_WIDTH = 269; //For description fields
private static final int FIELD_WIDTH = 70;
private static final int FIELD_WIDTH2 = 60;
private static final int FIELD_WIDTH3 = 60;
private static final int FIELD1 = 112;
private static final int VALUE1 = 112;
private static final int FIELD2 = 80;
private static final int VALUE2 = 80;
private static final int VALUE_WIDTH = 80;
private static final int VALUE_WIDTH2 = 60;
private static final int VALUE_WIDTH3 = 80;
private static final int HALF_WIDTH = 325;
private static final int TEXT_WIDTH = 410; //For text fields
private final RwaConstants constants = ConstantsGetter.getInstance();
private final PDDocument doc;
private final String logoPath;
private final String[] header;
private int count = 0;
private boolean newPage;
private PDPageContentStream content;
/**
* Empty constructor. Used only to initialize the rendering class and call
* it's methods.
*/
public PdfRenderingEndorsement(PDDocument doc, String logoPath,
String[] header) {
this.doc = doc;
this.logoPath = logoPath;
this.header = header;
}
public float checkContentStream2(float y, int lines, int space)
throws Exception {
float newY = checkYCoord2(y, lines, space);
if (newY == 700) {
if (content != null) {
content.close();
}
File file = new File(logoPath);
PDJpeg logoImg = new PDJpeg(doc, new FileInputStream(file));
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
doc.addPage(page);
content = new PDPageContentStream(doc, page);
content.drawImage(logoImg, 50, 720);
rHeader();
}
return newY;
}
private float checkYCoord2(float y, int lines, int space) {
float newY = y;
for (int i = 0; i < lines; i++) {
if ((newY - space) <= BOTTOM_MARGIN) {
newY = 700f;
return newY;
} else {
newY = newY - space;
}
}
return y;
}
public boolean getNewPage() {
return newPage;
}
public float checkContentStream(float y) throws Exception {
float newY = checkYCoord(y, 1, 10);
if (newY == 700) {
if (content != null) {
content.close();
}
File file = new File(logoPath);
PDJpeg logoImg = new PDJpeg(doc, new FileInputStream(file));
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
doc.addPage(page);
content = new PDPageContentStream(doc, page);
content.drawImage(logoImg, 50, 720);
rHeader();
}
return newY;
}
public float checkYCoord(float y, int lines, int space) {
float newY = y;
for (int i = 0; i < lines; i++) {
if ((newY - space) <= BOTTOM_MARGIN) {
newY = 700f;
return newY;
} else {
newY = newY - space;
}
}
return y;
}
public float checkContentStream(float y, int lines, int space)
throws Exception {
float newY = checkYCoord(y, lines, space);
if (newY == 700) {
if (content != null) {
content.close();
}
File file = new File(logoPath);
PDJpeg logoImg = new PDJpeg(doc, new FileInputStream(file));
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
doc.addPage(page);
content = new PDPageContentStream(doc, page);
content.drawImage(logoImg, 50, 720);
rHeader();
}
return newY;
}
public void closeContentStream() throws Exception {
if (content != null) {
content.close();
}
}
/**
* Renders the header for slip documents.
*/
public void rHeader() throws Exception {
float y = 760f;
content.setLineWidth(.5f);
content.setFont(PDType1Font.TIMES_ROMAN, 9);
content.setNonStrokingColor(Color.GRAY);
content.drawLine(50, 710, 562, 710);
y = rText(150, y + 19, 10, constants.endorsement(), null,
TEXT_WIDTH, 0);
y = rText(150, y + 9, 10, header[0], null, TEXT_WIDTH, 0);
y = rText(150, y + 9, 10, header[1], null, TEXT_WIDTH, 0);
y = rText(150, y + 9, 10, header[2], null, TEXT_WIDTH, 0);
y = rText(150, y + 9, 10, header[3], null, TEXT_WIDTH, 0);
content.setNonStrokingColor(Color.BLACK);
content.setFont(PDType1Font.TIMES_ROMAN, 9);
}
public float rText(float x, float y, int space, String labelField,
String value)
throws Exception {
return rText(x, y, space, labelField, value, FIELD_WIDTH,
HALF_WIDTH - 2 * FIELD_WIDTH - 10);
}
public float rTextLR(float x, float y, int space, String labelField,
String value)
throws Exception {
return rText(x, y, space, labelField, value, 0,
HALF_WIDTH - 2 * FIELD_WIDTH - 10);
}
public float rText(float x, float y, int space, String labelField,
String value, int fieldWidth)
throws Exception {
if (fieldWidth == 0) {
return rText(x, y, space, labelField, value, FIELD_WIDTH2,
VALUE_WIDTH2);
} else if (fieldWidth == 1) {
return rText(x, y, space, labelField, value, FIELD_WIDTH3,
VALUE_WIDTH3);
} else if (fieldWidth == 2) {
return rText(x, y, space, labelField, value, TEXT_WIDTH,
TEXT_WIDTH);
}
return y;
}
public float getFieldSize(int fs) {
switch(fs) {
case 1:
return (FIELD_WIDTH + VALUE_WIDTH);
case 2:
return (FIELD_WIDTH + DESC_WIDTH);
case 3:
return (FIELD_WIDTH + TEXT_WIDTH);
case 4:
return (HALF_WIDTH - FIELD_WIDTH);
case 5:
return (FIELD_WIDTH + TEXT_WIDTH);
case 6:
return (FIELD_WIDTH + TEXT_WIDTH);
case 7:
return (FIELD1 + 19) / 2;
case 8:
return (FIELD2 + 19) / 2;
default:
return 0;
}
}
public void paintLinesH(float y) throws Exception {
content.drawLine(49, y - 6, 327, y - 6);
content.drawLine(335, y - 6, 563, y - 6);
}
public void paintLinesV(float x, float yMax, float yMin)
throws Exception {
content.drawLine(x - 1, yMax - 6, x - 1, yMin - 6);
}
public float rText(float x, float y, int space, String labelField,
String value, int fieldWidth, int valueWidth)
throws Exception {
PDFont font = PDType1Font.TIMES_BOLD;
content.setFont(font, 9);
float y1 = 0f;
float y2 = 0f;
if (value == null) {
return rText(labelField, fieldWidth, x, y - 19, space, font, false);
} else {
if (labelField == null) {
font = PDType1Font.TIMES_ROMAN;
content.setFont(font, 9);
return rText(value, valueWidth, x, y - 19, space, font, true);
} else {
y1 = rText(labelField, fieldWidth, x, y - 30, space, font,
false);
font = PDType1Font.TIMES_ROMAN;
content.setFont(font, 9);
float y3 = y;
y2 = rText(value, valueWidth, x + fieldWidth + 10, y - 30,
space, font, true);
if (y3 < y2) {
return y2;
} else {
if (y1 >= y2) {
return y2;
} else {
return y1;
}
}
}
}
}
private ArrayList<String> getRows(String text, int width, PDFont font)
throws Exception {
float textWidth = font.getStringWidth(text) / 1000f * 9f;
ArrayList<String> result = Lists.newArrayList();
if (textWidth < width) {
result.add(text);
return result;
}
float spaceWidth = font.getStringWidth(" ") / 1000f * 9f;
String[] paragraphs = text.split("\n|\r\n|\r");
for (String paragraph : paragraphs) {
float pWidth = font.getStringWidth(paragraph) / 1000f * 9f;
if (pWidth < width) {
result.add(paragraph);
continue;
}
float widthCount = 0f;
String[] words = paragraph.trim().split(" ");
StringBuilder sb = new StringBuilder();
for (int j = 0; j < words.length; j++) {
if (words[j].trim().length() == 0) {
continue;
}
float wWidth = font.getStringWidth(words[j]) / 1000f * 9f;
float totalWidth = widthCount + wWidth + spaceWidth;
if (totalWidth < width + spaceWidth) {
sb.append(words[j]);
sb.append(" ");
widthCount = totalWidth;
} else {
result.add(sb.toString().trim());
sb = new StringBuilder();
sb.append(words[j]);
sb.append(" ");
widthCount = totalWidth - widthCount;
}
}
result.add(sb.toString().trim());
}
return result;
}
private float rText(String text, int width, float x, float y, int space,
PDFont font, boolean isValue) throws Exception {
float newY = y;
int rowHeight = 0;
newPage = false;
ArrayList<String> rowList = getRows(text, width, font);
if (isValue) {
for (String row : rowList) {
if (rowHeight >= 10) {
newY = checkContentStream(newY - 10);
newY = newY == 700 ? 680 : newY;
if (newY <= 700 && !newPage) {
newPage = true;
}
rowHeight = newY == 680 ? 0 : rowHeight;
}
content.beginText();
content.moveTextPositionByAmount(x, newY);
content.drawString(row);
content.endText();
rowHeight = rowHeight + 10;
}
} else {
for (String row : rowList) {
content.beginText();
content.moveTextPositionByAmount(x, newY - rowHeight);
content.drawString(row);
content.endText();
rowHeight = rowHeight + 10;
}
newY -= (rowHeight - 10);
}
return newY;
}
}
這是原始( for-each
)方法輸出的PDF示例 。
如果您看不到PDF,請告訴我,但是這里還有一些屏幕截圖:
這是帶有getMinY
方法上未注釋代碼的輸出的PDF示例 。
通過此修改,這里是輸出:
如您所見,第一個輸出“跳轉”到下一頁,因為假設“ Texto de Poliza”右側的文本在Y坐標680、670或類似位置處結束,但是在左側我畫了一個空白字段("")
,其結尾數接近這些數字的90或100。
然后比較100 <670? 是的,然后我取了50到100,它比我的BOTTOM_MARGIN
(它是60)低,因此它關閉了實際頁面(現在是文本結尾的位置,但認為它在它之前的頁面上)並創建了一個新頁面。
我問過類似的問題差不多一年之前這里 ,這些類是幾乎從這些文件的副本,但因為數據處理方式稍有不同在我的邏輯這個bug與這些文件只配備。
好在那堵文字牆之后,我希望有人能讀懂它並實際上幫我忙,也許我錯過了重要的一部分,但找不到自動取款機。
提前致謝。
編輯
在將@mkl的答案添加到我的方法中后,我發現,如果雙方的信息均未更改,則會造成差距,而且效果也不佳。
這就是我將數據發送到PdfRenderingEndorsementAlternative
:
for (String[] data: sOppData) {
//float y = renderer.getPreviousBandBase;
for (int i = 0; i < data.length - 2; i += 3) {
if (!nullOrEmpty(data[i + 1]) &&
!nullOrEmpty(data[i + 2])) {
if (!data[i + 1].equals(data[i + 2])) {
renderer.
render(new BandColumn(leftHalfPageField,
data[i], data[i + 1]),
new BandColumn(rightHalfPageField,
data[i], data[i + 2])
);
}
} else if (nullOrEmpty(data[i + 1]) &&
!nullOrEmpty(data[i + 2])) {
renderer.
render(new BandColumn(leftHalfPageField,
"", ""),
new BandColumn(rightHalfPageField,
data[i], data[i + 2])
);
} else if (!nullOrEmpty(data[i + 1]) &&
nullOrEmpty(data[i + 2])) {
renderer.
render(new BandColumn(leftHalfPageField,
data[i], data[i + 1]),
new BandColumn(rightHalfPageField,
"", "")
);
}
}
//float y2 = renderer.getPreviousBandBase();
/*if (y2 < y)
renderer.gap(20);
*/
renderer.gap(20);
}
以上評論的驗證是否正確,還是我將回到過去引發錯誤的方法? 我應該在PdfRenderingEndorsementAlternative上添加getPreviousBandBase()
方法還是以其他方式直接在render()
方法上進行操作?
這就是我如何獲取雙方當前具有相同信息的數據。
例如:
sOppA.getContractName()
和sOppE.getContractName()
都是"Hello World"
,並且兩者相等,因此會留出間隙,如屏幕截圖所示。
private ArrayList<String []> renderSubscriptionOpportunity(
SubscriptionOpp sOppA, SubscriptionOpp sOppE,
ArrayList<Location> lcA, ArrayList<Location> lcE)
throws Exception {
ArrayList <String[]> sOppData = new ArrayList<String[]>();
sOppData.add(new String[] {constants.currencyId(),
getStringValue(sOppA.getCurrencyId(),
Currency.class),
getStringValue(sOppE.getCurrencyId(),
Currency.class)});
sOppData.add(new String[] {constants.contractName(),
getStringValue(sOppA.getContractName()),
getStringValue(sOppE.getContractName())});
sOppData.add(new String[] {constants.mainActivityId(),
getStringValue(sOppA.getMainActivityId(),
MainActivity.class),
getStringValue(sOppE.getMainActivityId(),
MainActivity.class)});
//here add location table
if (lcA.size() > 1 && lcE.size() > 1) {
int lastIdA = 0;
int lastIdE = 0;
int size = lcA.size() >= lcE.size() ? lcA.size() : lcE.size();
LOGGER.trace("size: " + size + " lcA.size(): " + lcA.size() +
" lcE.size(): " + lcE.size());
for (int pos = 1; pos < lcA.size(); pos++) {
StringBuilder aSb = new StringBuilder();
StringBuilder eSb = new StringBuilder();
String valueA = "";
String valueE = "";
if (pos < lcA.size()) {
Country countryA = unitSvc.get(Country.class,
lcA.get(pos).getCountryId());
LOGGER.trace("Entro1");
if (countryA.getId() != lastIdA) {
aSb.append(countryA.getName());
lastIdA = countryA.getId();
} else {
aSb.append("");
}
} else {
aSb.append("");
}
if (pos < lcE.size()) {
Country countryE = unitSvc.get(Country.class,
lcE.get(pos).getCountryId());
LOGGER.trace("Entro2");
if (countryE.getId() != lastIdE) {
eSb.append(countryE.getName());
lastIdE = countryE.getId();
} else {
eSb.append("");
}
} else {
eSb.append("");
}
valueA = aSb.toString();
valueE = eSb.toString();
sOppData.add(new String[] {pos == 1 ? constants.countryId() :
"", valueA, valueE});
}
}
return sOppData;
}
正如評論中已經暗示的那樣(實際上已經在對您先前的問題的評論中),我認為您的渲染類的整個體系結構都需要進行大修。 基於您的PdfRenderingEndorsement
我創建了以下類PdfRenderingEndorsementAlternative
,它表示該渲染的另一種方法:
public class PdfRenderingEndorsementAlternative implements AutoCloseable
{
//
// misc constants
//
static final int FIELD_WIDTH = 70;
static final int HALF_WIDTH = 325;
static final int TEXT_WIDTH = 410;
static final float BOTTOM_MARGIN = 70;
static final int LEFT_MARGIN = 50;
//
// rendering
//
public void gap(int size)
{
previousBandBase-=size;
}
public void render(BandColumn... columns) throws IOException
{
if (content == null)
newPage();
final List<Chunk> chunks = new ArrayList<Chunk>();
for (BandColumn column : columns)
{
chunks.addAll(column.toChunks());
}
float offset = 0;
while (!chunks.isEmpty())
{
float lowestAddedY = previousBandBase;
float highestBaseBeforeNonAdded = Float.NEGATIVE_INFINITY;
List<Chunk> added = new ArrayList<Chunk>();
for (Chunk chunk: chunks)
{
float y = previousBandBase + chunk.y + offset;
if (y >= BOTTOM_MARGIN)
{
content.beginText();
content.setFont(chunk.font, 9);
content.moveTextPositionByAmount(chunk.x, y);
content.drawString(chunk.text);
content.endText();
// draw
if (y < lowestAddedY)
lowestAddedY = y;
added.add(chunk);
}
else
{
float baseBefore = chunk.y + chunk.space;
if (baseBefore > highestBaseBeforeNonAdded)
highestBaseBeforeNonAdded = baseBefore;
}
}
chunks.removeAll(added);
if (!chunks.isEmpty())
{
newPage();
offset = -highestBaseBeforeNonAdded;
}
else
{
previousBandBase = lowestAddedY;
}
}
}
static public class BandColumn
{
public enum Layout
{
headerText(150, TEXT_WIDTH, 0, 10),
leftHalfPageField(LEFT_MARGIN, FIELD_WIDTH, HALF_WIDTH - 2 * FIELD_WIDTH - 10, 10),
rightHalfPageField(HALF_WIDTH, FIELD_WIDTH, HALF_WIDTH - 2 * FIELD_WIDTH - 10, 10);
Layout(float x, int fieldWidth, int valueWidth, int space)
{
this.x = x;
this.fieldWidth = fieldWidth;
this.valueWidth = valueWidth;
this.space = space;
}
final float x;
final int fieldWidth, valueWidth, space;
}
public BandColumn(Layout layout, String labelField, String value)
{
this(layout.x, layout.space, labelField, value, layout.fieldWidth, layout.valueWidth);
}
public BandColumn(float x, int space, String labelField, String value, int fieldWidth, int valueWidth)
{
this.x = x;
this.space = space;
this.labelField = labelField;
this.value = value;
this.fieldWidth = fieldWidth;
this.valueWidth = valueWidth;
}
List<Chunk> toChunks() throws IOException
{
final List<Chunk> result = new ArrayList<Chunk>();
result.addAll(toChunks(0, fieldWidth, PDType1Font.TIMES_BOLD, labelField));
result.addAll(toChunks(10 + fieldWidth, valueWidth, PDType1Font.TIMES_ROMAN, value));
return result;
}
List<Chunk> toChunks(int offset, int width, PDFont font, String text) throws IOException
{
if (text == null || text.length() == 0)
return Collections.emptyList();
final List<Chunk> result = new ArrayList<Chunk>();
float y = -space;
List<String> rows = getRows(text, width, font);
for (String row: rows)
{
result.add(new Chunk(x+offset, y, space, font, row));
y-= space;
}
return result;
}
final float x;
final int space, fieldWidth, valueWidth;
final String labelField, value;
}
//
// constructor
//
public PdfRenderingEndorsementAlternative(PDDocument doc, InputStream logo,
String[] header) throws IOException
{
this.doc = doc;
this.header = header;
logoImg = new PDJpeg(doc, logo);
}
//
// AutoCloseable implementation
//
@Override
public void close() throws IOException
{
if (content != null)
{
content.close();
content = null;
}
}
//
// helper methods
//
void newPage() throws IOException
{
close();
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
doc.addPage(page);
content = new PDPageContentStream(doc, page);
content.drawImage(logoImg, 50, 720);
content.setLineWidth(.5f);
content.setNonStrokingColor(Color.GRAY);
content.drawLine(50, 710, 562, 710);
previousBandBase = 770;
render(new BandColumn(BandColumn.Layout.headerText, "ENDOSO", null));
for (String head: header)
render(new BandColumn(BandColumn.Layout.headerText, head, null));
content.setNonStrokingColor(Color.BLACK);
previousBandBase = 680;
}
// original method
static List<String> getRows(String text, int width, PDFont font) throws IOException
{
float textWidth = font.getStringWidth(text) / 1000f * 9f;
ArrayList<String> result = new ArrayList<String>();// Lists.newArrayList();
if (textWidth < width)
{
result.add(text);
return result;
}
float spaceWidth = font.getStringWidth(" ") / 1000f * 9f;
String[] paragraphs = text.split("\n|\r\n|\r");
for (String paragraph : paragraphs)
{
float pWidth = font.getStringWidth(paragraph) / 1000f * 9f;
if (pWidth < width)
{
result.add(paragraph);
continue;
}
float widthCount = 0f;
String[] words = paragraph.trim().split(" ");
StringBuilder sb = new StringBuilder();
for (int j = 0; j < words.length; j++)
{
if (words[j].trim().length() == 0)
{
continue;
}
float wWidth = font.getStringWidth(words[j]) / 1000f * 9f;
float totalWidth = widthCount + wWidth + spaceWidth;
if (totalWidth < width + spaceWidth)
{
sb.append(words[j]);
sb.append(" ");
widthCount = totalWidth;
}
else
{
result.add(sb.toString().trim());
sb = new StringBuilder();
sb.append(words[j]);
sb.append(" ");
widthCount = totalWidth - widthCount;
}
}
result.add(sb.toString().trim());
}
return result;
}
//
// helper classes
//
static class Chunk
{
Chunk(float x, float y, int space, PDFont font, String text)
{
this.x = x;
this.y = y;
this.space = space;
this.font = font;
this.text = text;
}
final float x, y;
final int space;
final PDFont font;
final String text;
}
//
// members
//
private final PDDocument doc;
private final PDJpeg logoImg;
private final String[] header;
private PDPageContentStream content = null;
private float previousBandBase = 0;
}
此類基於帶的概念,即內容的水平條紋,具有包含字段名稱和/或字段值的任意數量的列。
可以這樣使用:
PDDocument document = new PDDocument();
PdfRenderingEndorsementAlternative renderer = new PdfRenderingEndorsementAlternative(document, logoStream, header);
renderer.render(
new BandColumn(leftHalfPageField, "Nombre del contrato/asegurado:", "Prueba Jesus Fac No Prop"),
new BandColumn(rightHalfPageField, "Nombre del contrato/asegurado:", "Prueba Jesus Fac No Prop con Endoso")
);
renderer.gap(20);
renderer.render(
new BandColumn(leftHalfPageField, "País:", "México"),
new BandColumn(rightHalfPageField, "País:", "México")
);
renderer.close();
document.save(new File(RESULT_FOLDER, "Endorsement.pdf"));
如您所見,調用者不必再關心y位置了,所有事情都在renderer類中完成。 結果:
我將您的第一個樣本PDF中的數據用作輸入,結果如下:
如您所見,也沒有頁面跳轉,也沒有重疊的文本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.