Создайте таблицу с повторяющимся заголовком с iText

Sameer спросил: 28 апреля 2018 в 09:43 в: java

Я хочу создать таблицу с повторяющимися заголовками, такими как изображение, которое я прикреплял к своему сообщению.

Я хочу заполнить первые три столбца слева до конца таблицы, а затем заполнить второй три столбца справа от таблицы.

Я использовал одну таблицу с шестью столбцами, как показано на странице. Я извлек данные из базы данных в соответствии с порядком даты, и я хочу поместить свои данные в таблицу как изображение.

Я могу создать таблицу с iText в java, но я не знаю, как создать таблицу с этим стилем в iText. пожалуйста, помогите мне, если это возможно.


2 ответа

Joris Schellekens ответил: 04 мая 2018 в 11:50

Это относительно просто.

Сначала я создал класс, представляющий одну запись.

static class Record{
    public String firstname;
    public String lastname;
    public Record(String firstname, String lastname){
        this.firstname = firstname;
        this.lastname = lastname;
    }
    public String getFirstname(){return firstname;}
    public String getLastname(){return lastname;}
    public boolean equals(Object o){
        if(o instanceof Record){
            Record r = (Record) o;
            return r.firstname.equals(firstname) && r.lastname.equals(lastname);
        }
        return false;
    }
}

Я также создал метод, который случайным образом генерирует объекты такого рода, используя символы Симпсонов.

private static Random RANDOM = new Random(System.currentTimeMillis());
public Record randomRecord(){
    String[] fn = {"Marge", "Homer", "Bart", "Lisa", "Nelson", "Apu", "Doris", "Seymour"};
    String[] ln = {"Bouvier", "Simpson", "Muntz", "Nahasapeemapetilan", "Skinner"};
    return new Record(fn[RANDOM.nextInt(fn.length)], ln[RANDOM.nextInt(ln.length)]);
}

Код для создания таблицы выглядит следующим образом:

    List<Record> recordList = new ArrayList<>();
    for(int i=0;i<17;i++)
        recordList.add(randomRecord());    File outputFile = getOutputFile();
    PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outputFile));
    Document layoutDocument = new Document(pdfDocument);    int numberOfItemsInFirstHalf = (int) Math.ceil(recordList.size() / 2.0);    Table table = new Table(new float[]{0.16f, 0.16f, 0.16f, 0.16f, 0.16f, 0.16f});    // header
    for(int i=0;i<2;i++) {
        table.addCell(new Cell().add(new Paragraph("Number")).setBackgroundColor(new DeviceRgb(74,189,172)));
        table.addCell(new Cell().add(new Paragraph("Firstname")).setBackgroundColor(new DeviceRgb(74,189,172)));
        table.addCell(new Cell().add(new Paragraph("Lastname")).setBackgroundColor(new DeviceRgb(74,189,172)));
    }    // table
    for(int i=0;i<numberOfItemsInFirstHalf;i++){
        Record r0 = recordList.get(i);
        Record r1 = (i+numberOfItemsInFirstHalf) < recordList.size() ? recordList.get(i + numberOfItemsInFirstHalf) : null;        table.addCell(new Cell().add(new Paragraph((i + 1)+"")));
        table.addCell(new Cell().add(new Paragraph(r0.getFirstname())));
        table.addCell(new Cell().add(new Paragraph(r0.getLastname())));        if(r1 == null){
            table.addCell(new Cell().add(new Paragraph("")));
            table.addCell(new Cell().add(new Paragraph("")));
            table.addCell(new Cell().add(new Paragraph("")));
        }else{
            table.addCell(new Cell().add(new Paragraph((i + numberOfItemsInFirstHalf + 1)+"")));
            table.addCell(new Cell().add(new Paragraph(r1.getFirstname())));
            table.addCell(new Cell().add(new Paragraph(r1.getLastname())));
        }
    }    layoutDocument.add(table);    pdfDocument.close();

, который генерирует следующий документ в формате PDF:

Sameer ответил: 04 мая 2018 в 05:09
Большое спасибо за ваш ответ. Я проверил ваш код, но результат не соответствует моему запросу. например, если у меня есть запись 250, записи делятся на две страницы, а число помещается друг под друга друг под друга. На первой странице последнее число равно 53, а первое число второй - 54, и это неправильно. Я хочу иметь 54-ю запись на первой странице сразу после этого 53 во вторых трех столбцах справа.
Joris Schellekens ответил: 04 мая 2018 в 05:14
Да, этот код, очевидно, не учитывает разбивку на страницы. Если вы этого хотите, вам нужно будет отслеживать, где таблица разбита. Но основной принцип был бы таким же.
Sameer ответил: 05 мая 2018 в 06:19
Спасибо. Есть ли способ узнать, где таблица разбита?
Joris Schellekens ответил: 05 мая 2018 в 06:23
При добавлении IElement в документ вы можете запросить Renderer для своих детей. Если таблица разделена, вы ожидаете увидеть SplitRenderer.
Sameer ответил: 05 мая 2018 в 07:11
Я искал через intenet, но я не мог найти никакого примера, который используется SplitRenderer. Я новичок, и до сих пор я использовал простую структуру iText до сих пор, поэтому я не имею никакого представления о SplitRenderer, но я стараюсь изо всех сил. Спасибо большое.
Uladzimir Asipchuk ответил: 05 мая 2018 в 07:55

Я не совсем понял, как вы хотите, чтобы ваша таблица была обработана на split, и предположила, что вы ищете макет из двух столбцов. Если это так, для вас существует предопределенный класс ColumnDocumentRenderer. Если он установлен в экземпляре Document, он позволяет размещать содержимое документа в столбцах.

Итак, я определил столбцы:

Rectangle pageSize = pdfDocument.getDefaultPageSize(); Rectangle[] areas = new Rectangle[2]; areas[0] = new Rectangle(36, 36, ((float) pageSize.getWidth() / 2) - 35.75f, pageSize.getHeight() - 72); areas[1] = new Rectangle((float) pageSize.getWidth() / 2 - 0.25f, 36, ((float) pageSize.getWidth() / 2) - 35.75f , pageSize.getHeight() - 72);

И затем я применил средство визуализации к экземпляру Document: layoutDocument.setRenderer(new ColumnDocumentRenderer(layoutDocument, areas));

Результат на разбиении выглядит следующим образом:

Код полностью:

    @Test
public void tableTest02() throws Exception {
    String outFileName = destinationFolder + "tableTest02.pdf";
    String cmpFileName = sourceFolder + "cmp_tableTest02.pdf";    PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
    Document layoutDocument = new Document(pdfDocument);    Table table = new Table(3);
    table.setWidth(UnitValue.createPercentValue(100));    Rectangle pageSize = pdfDocument.getDefaultPageSize();
    Rectangle[] areas = new Rectangle[2];
    areas[0] = new Rectangle(36, 36, ((float) pageSize.getWidth() / 2) - 35.75f, pageSize.getHeight() - 72);
    areas[1] = new Rectangle((float) pageSize.getWidth() / 2 - 0.25f, 36, ((float) pageSize.getWidth() / 2) - 35.75f , pageSize.getHeight() - 72);    layoutDocument.setRenderer(new ColumnDocumentRenderer(layoutDocument, areas));
    // header
    for(int i=0;i<1;i++) {
        table.addHeaderCell(new Cell().add(new Paragraph("Number")).setBackgroundColor(new DeviceRgb(74,189,172)));
        table.addHeaderCell(new Cell().add(new Paragraph("Firstname")).setBackgroundColor(new DeviceRgb(74,189,172)));
        table.addHeaderCell(new Cell().add(new Paragraph("Lastname")).setBackgroundColor(new DeviceRgb(74,189,172)));
    }    // table
    for(int i=0;i<500;i++){        table.addCell(new Cell().add(new Paragraph((i + 1)+"")));
        table.addCell(new Cell().add(new Paragraph("Hello")));
        table.addCell(new Cell().add(new Paragraph("World")));    }    layoutDocument.add(table);    pdfDocument.close();    Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
}

Трудный момент состоял в том, чтобы свернуть границы таблицы, но увеличивая ширину с 0.25f и перемещая правый столбец 0.25f слева я достиг границ, которые будут размещены один на другом.

Sameer ответил: 05 мая 2018 в 10:46
Я прикрепил изображение к своему первому сообщению, которое показывает стиль таблицы, которую я хочу. Я загрузил стиль, который я хочу, в следующий адрес again.ufile.io/uppi0. Я хочу иметь этот стиль на каждой странице, например, вторую страницу начинается с номера 42 до 82 и так далее.
Uladzimir Asipchuk ответил: 05 мая 2018 в 11:14
1) Итак, что в заголовке recetitive вы подразумеваете, что заголовок должен повторяться только на первой странице? 2) Suppost, что 20 строк могут быть размещены на странице. Какой результат вы ожидаете: a) или b)? a) 1 11 \ n 2 12 \ n ...... \ n 10 20 \ n PAGEBREAK 21 31 \ n 22 32 \ n ........ \ n 30 40 \ nb) 1 21 \ n 2 22 \ n ...... \ n 10 30 \ n PAGEBREAK 11 31 \ n 12 32 \ n ........ \ n 20 40 \ n
Sameer ответил: 05 мая 2018 в 04:47
Я имею в виду, что на каждой странице у меня есть таблица с этими столбцами: номер, имя, фамилия, номер, имя, фамилия. Затем я хочу заполнить их точно так же, как изображение, которое я прикрепляю, и точную нумерацию, показанную на картинке, и заполнить таблицу этим рисунком (как показано на рисунке) до тех пор, пока данные не будут завершены. Другими словами, я хочу, чтобы 41 запись на первой странице в стиле, показанном на рисунке, и 41 запись на второй странице и так далее.
Uladzimir Asipchuk ответил: 06 мая 2018 в 05:50
Хорошо, поэтому код, указанный в ответе, поможет вам тогда.
Sameer ответил: 06 мая 2018 в 07:30
Нет, это не так, потому что он создал одну таблицу с столбцом 3column not 6, как я сказал, и пронумеровать каждую строку. Это не соответствовало стилю, который я хочу вообще.