2016-06-11 3 views
1

Я создал документы, используя itext 7 и его ColumnDocumentRenderer. Я хотел бы добавить текст в последний столбец. Под «последним столбцом» я имею в виду, например, если у меня есть одна страница, определенная ColumnDocumentRenderer, чтобы иметь 3 столбца, но у меня есть только один столбец текста, я все равно хочу, чтобы столбец 3 содержал мое принудительное значение. Поэтому я полагаю (предполагая решение, другие оценили), что мне понадобятся механизмы, чтобы знать номер столбца, в котором я находился, и заставить разрывать столбцы. Поскольку StackOverflow хочет это в форме вопроса, (а) каковы эти механизмы? и (б) какие альтернативные подходы?Как определить номер столбца с помощью itext 7

Вопрос How to skip text insertion point to the next column using iText?, по-видимому, задает аналогичный вопрос, но, по-видимому, использует более раннее освобождение itext; у меня нет ColumnText, который я могу найти.

Заранее благодарим за любую помощь.

+0

Я бы создал свой собственный рендер. Следите за столбцом, как это сделано в [документации] (http://developers.itextpdf.com/content/itext-7-building-blocks/chapter-2-working-rootelement), более конкретно, я перезаписал 'updateCurrentArea()' и выставить 'currentAreaNumber'. Я бы проверил этот номер перед добавлением содержимого, которое входит в третий столбец, и добавьте столько объектов «AreaBreak», сколько необходимо. Примечание: по какой-то причине переменная 'currentAreaNumber' является' private'. Я соблазн сделать его «защищенным». –

+0

Я очень ценю ссылку на документацию. Я следил за различными ссылками через сайт itext, но не нашел документацию, специфичную для itext7. еще раз спасибо. – OldAndTired

+0

Работал отлично – OldAndTired

ответ

1

Я отвечал с телефона вчера, но теперь, когда у меня есть доступ к компьютеру, я изменил ColumnDocumentRenderer так:

public class ColumnDocumentRenderer extends DocumentRenderer { 

    protected Rectangle[] columns; 
    protected int nextAreaNumber; 

    public ColumnDocumentRenderer(Document document, Rectangle[] columns) { 
     super(document); 
     this.columns = columns; 
    } 

    public ColumnDocumentRenderer(Document document, boolean immediateFlush, Rectangle[] columns) { 
     super(document, immediateFlush); 
     this.columns = columns; 
    } 

    @Override 
    protected LayoutArea updateCurrentArea(LayoutResult overflowResult) { 
     if (overflowResult != null && overflowResult.getAreaBreak() != null && overflowResult.getAreaBreak().getType() != AreaBreakType.NEXT_AREA) { 
      nextAreaNumber = 0; 
     } 
     if (nextAreaNumber % columns.length == 0) { 
      super.updateCurrentArea(overflowResult); 
     } 
     return (currentArea = new LayoutArea(currentPageNumber, columns[nextAreaNumber++ % columns.length].clone())); 
    } 

    public int getNextAreaNumber() { 
     return nextAreaNumber; 
    } 
} 

Изменение будет IText 7.0.1, но вы можете использовать этот кода в вашем собственном рендерере.

Теперь вы можете использовать этот визуализатор так:

public void createPdf(String dest) throws IOException { 
    OutputStream fos = new FileOutputStream(dest); 
    PdfWriter writer = new PdfWriter(fos); 
    PdfDocument pdf = new PdfDocument(writer); 
    Document document = new Document(pdf); 

    float offSet = 36; 
    float gutter = 23; 
    float columnWidth = (PageSize.A4.getWidth() - offSet * 2)/3 - gutter * 2; 
    float columnHeight = PageSize.A4.getHeight() - offSet * 2; 
    Rectangle[] columns = { 
     new Rectangle(offSet, offSet, columnWidth, columnHeight), 
     new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight), 
     new Rectangle(offSet + 2 * (columnWidth + gutter), offSet, columnWidth, columnHeight)}; 
    ColumnDocumentRenderer renderer = new ColumnDocumentRenderer(document, columns); 
    document.setRenderer(renderer); 

    for (int i = 0; i < 50; i++) { 
     document.add(new Paragraph("Hello World")); 
    } 
    while (renderer.getNextAreaNumber() % 3 != 0) 
     document.add(new AreaBreak()); 
    document.add(new Paragraph("Third column")); 
    document.add(new AreaBreak()); 
    for (int i = 0; i < 80; i++) { 
     document.add(new Paragraph("Hello World")); 
    } 
    while (renderer.getNextAreaNumber() % 3 != 0) 
     document.add(new AreaBreak()); 
    document.add(new Paragraph("Third column")); 
    document.add(new AreaBreak()); 
    for (int i = 0; i < 10; i++) { 
     document.add(new Paragraph("Hello World")); 
    } 
    while (renderer.getNextAreaNumber() % 3 != 0) 
     document.add(new AreaBreak()); 
    document.add(new Paragraph("Third column")); 
    document.close(); 

} 

Первый столбец имеет индекс 0, а следующая область число 1, то второй столбец имеет индекс 1 и следующей области число равно 2, и так на.

Это означает, что вы можете проверить и перейти в третий столбец на странице, подобной этой.

while (renderer.getNextAreaNumber() % 3 != 0) 
    document.add(new AreaBreak()); 
+0

Разве не имеет смысла отделять новый метод ColumnDocumentRenderer от деталей реализации, вернуть ли он * текущий номер области и называть его 'getAreaNumber'? В конце концов, обычно пользователь хочет знать, в каком столбце он находится, а не о следующем. (Да, легко выводить один из другого, но иметь способ получить текущий столбец для меня более интуитивно, чем использовать его для получения следующего.) – mkl

+0

Я думал об этом, и у меня была такая же идея , но затем я нашел несколько аргументов, которые заставили меня решить пойти на 'nextAreaNumber'. Я уже забыл эти аргументы, но я помню, что они были связаны с эффектом разрыва страницы. –

Смежные вопросы