Создание таблиц в файле MS Word с помощью Java

Я хочу создать таблицу в файле Microsoft Office Word с помощью Java. Кто-нибудь может сказать мне, как это сделать на примере?

Почему это вики сообщества? Это больше похоже на «обычный» вопрос.

eljenso 30.12.2008 12:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
1
15 019
9

Ответы 9

Я никогда не видел, чтобы это было сделано, и я много работаю в Word. Если вы действительно хотите программно сделать что-то в текстовом документе, я бы посоветовал использовать язык сценариев Microsoft VBA, который специально разработан для этой цели. Собственно, я сейчас работаю над этим.

Если вы работаете в Open Office, то у них есть очень похожий набор инструментов на основе макросов для выполнения того же самого.

Взгляните на POI Apache

The POI project is the master project for developing pure Java ports of file formats based on Microsoft's OLE 2 Compound Document Format. OLE 2 Compound Document Format is used by Microsoft Office Documents, as well as by programs using MFC property sets to serialize their document objects.

Офисный писатель будет лучшим инструментом для использования, чем POI для ваших требований.

Если вам нужна простая таблица без особого форматирования, я бы использовал этот простой трюк. Используйте Java, чтобы сгенерировать таблицу как HTML с использованием простых тегов old table, tr, td, и скопируйте визуализированную HTML-таблицу в текстовый документ;)

URL больше не существует.

ianmayo 29.07.2020 11:35

Office 2003 имеет формат xml, а формат документа по умолчанию для Office 2007 - xml (заархивированный). Таким образом, вы можете просто сгенерировать xml из java. Если вы открываете существующий документ, это не так уж сложно, также увидеть требуемый xml.

В качестве альтернативы вы можете использовать api openoffice для создания документа и сохранить его как документ ms-word.

Наш набор функций состоит в том, чтобы нажать кнопку в нашем веб-приложении и получить страницу, которую вы просматриваете, обратно в виде документа Word. Мы используем схему docx для описания документов и имеем кучу кода Java на стороне сервера, который создает документ и отвечает нашему веб-клиенту. Само форматирование выполняется с помощью некоторых скомпилированных xsl-t из Java для перевода с нашего собственного уровня сохраняемости XML.

Схему docx понять довольно сложно. Мы добились наибольшего прогресса в создании шаблонов docx в Word с точно таким форматированием, которое нам было нужно, но с фиктивным содержимым. Затем мы дурачились, пока не поняли, что происходит. В docx очень много всего, о чем не стоит беспокоиться. При чтении / переводе docx Word довольно терпимо относится к частично полной схеме форматирования. Фактически, мы решили исключить практически все форматирование, потому что это также означает, что форматирование пользователя по умолчанию имеет приоритет, что они, похоже, предпочитают. Это также ускоряет процесс xsl и уменьшает размер итогового документа.

Щелкните здесь, чтобы получить Рабочий пример с исходным кодом. В этом примере создаются документы MS-Word из Java на основе концепции шаблона.

Я руковожу проектом docx4j

docx4j содержит класс TblFactory, который создает обычные таблицы (т. е. без промежутков строк или столбцов) с настройками по умолчанию, которые Word 2007 создаст, и с размерами, указанными пользователем.

Если вам нужна более сложная таблица, проще всего создать ее в Word, а затем скопировать полученный XML в строку в вашей среде IDE, где вы можете использовать docx4j XmlUtils.unmarshalString для создания из нее объекта Tbl.

Этот фрагмент можно использовать для динамического создания таблицы в документе MS Word.

WPFDocument document = new XWPFDocument();
XWPFTable tableTwo = document.createTable();
XWPFTableRow tableTwoRowOne = tableTwo.getRow(0);
tableTwoRowOne.getCell(0).setText(Knode1);
tableTwoRowOne.createCell().setText(tags.get("node1").toString());
for (int i = 1; i < nodeList.length; i++) {
    String node = "node";
    String nodeVal = "";
    XWPFTableRow tr = null;
    node = node + (i + 1);
    nodeVal = tags.get(node).toString();
    if (tr == null) {
        tr = tableTwo.createRow();
        tr.getCell(0).setText(nodeList[i]);
        tr.getCell(1).setText(tags.get(node).toString());
    }
}

Используя мою небольшую zip-утилиту, вы можете легко создавать docx, если знаете, что делаете. Формат файла DOCX Word - это просто zip (папки с файлами xml). Используя утилиты java zip, вы можете изменять существующий docx, только часть содержимого.

Чтобы следующий пример работал, просто откройте Word, введите несколько строк и сохраните документ. Затем с помощью программы zip удалите файл word / document.xml (это файл, в котором находится основное содержимое документа Word) из zip. Теперь у вас есть готовый шаблон. Сохраните измененный zip.

Вот как выглядит создание нового файла Word:

/* docx file head  */
    final String DOCUMENT_XML_HEAD =
            "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" +
            "<w:document xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" mc:Ignorable=\"w14 w15 wp14\">" +
            "<w:body>";

    /* docx file foot  */
    final String DOCUMENT_XML_FOOT =
             "</w:body>" +
             "</w:document>";


    final ZipOutputStream zos =  new ZipOutputStream(new FileOutputStream("c:\\TEMP\\test.docx"));

    final String fullDocumentXmlContent = DOCUMENT_XML_HEAD + "<w:p><w:r><w:t>Hey MS Word, hello from java.</w:t></w:r></w:p>" + DOCUMENT_XML_FOOT;

    final si.gustinmi.DocxZipCreator creator = new si.gustinmi.DocxZipCreator();

    // create new docx file
    creator.createDocxFromExistingDocx(zos, "c:\\TEMP\\existingDocx.docx", fullDocumentXmlContent);

Это zip-утилиты:

package si.gustinmi;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * Creates new docx from existing one.
 * @author gustinmi [at] gmail [dot] com
 */
public class DocxZipCreator {

    public static final Logger log = Logger.getLogger(DocxZipCreator.class.getCanonicalName());

    private static final int BUFFER_SIZE = 4096;


    /** OnTheFly zip creator. Traverses through existing docx zip and creates new one simultaneousl.
     * On the end, custom document.xml is inserted inside
     * @param zipFilePath location of existing docx template (without word/document.xml)
     * @param documentXmlContent content of the word/document.xml
     * @throws IOException
     */
    public void createDocxFromExistingDocx(ZipOutputStream zos, String zipFilePath, String documentXmlContent) throws IOException {

        final FileInputStream fis = new FileInputStream(zipFilePath);
        final ZipInputStream zipIn = new ZipInputStream(fis);

        try{
            log.info("Starting to create new docx zip");
            ZipEntry entry = zipIn.getNextEntry();
            while (entry != null) { // iterates over entries in the zip file
                copyEntryfromZipToZip(zipIn, zos, entry.getName());
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }

            // add document.xml to existing zip
            addZipEntry(documentXmlContent, zos, "word/document.xml");

        }finally{
            zipIn.close();
            zos.close();
            log.info("End of docx creation");
        }

    }

    /** Copies sin gle entry from zip to zip  */
    public void copyEntryfromZipToZip(ZipInputStream is, ZipOutputStream zos, String entryName)
    {
        final byte [] data = new byte[BUFFER_SIZE]; 
        int len; 
        int lenTotal = 0;
        try {

            final ZipEntry entry = new ZipEntry(entryName); 
            zos.putNextEntry(entry); 

            final CRC32 crc32 = new CRC32(); 
            while ((len = is.read(data)) > -1){ 
                zos.write(data, 0, len); 
                crc32.update(data, 0, len);
                lenTotal += len;
            } 

            entry.setSize(lenTotal); 
            entry.setTime(System.currentTimeMillis()); 
            entry.setCrc(crc32.getValue());

        }
        catch (IOException ioe){
            ioe.printStackTrace();
        }
        finally{
            try { zos.closeEntry();} catch (IOException e) {}
        }
    }

    /**  Create new zip entry with content
     * @param content content of a new zip entry
     * @param zos 
     * @param entryName name (npr: word/document.xml)
     */
    public void addZipEntry(String content, ZipOutputStream zos, String entryName)
    {
        final byte [] data = new byte[BUFFER_SIZE]; 
        int len; 
        int lenTotal = 0;
        try {

            final InputStream is = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));

            final ZipEntry entry = new ZipEntry(entryName); 
            zos.putNextEntry(entry); 

            final CRC32 crc32 = new CRC32(); 
            while ((len = is.read(data)) > -1){ 
                zos.write(data, 0, len); 
                crc32.update(data, 0, len);
                lenTotal += len;
            } 

            entry.setSize(lenTotal); 
            entry.setTime(System.currentTimeMillis()); 
            entry.setCrc(crc32.getValue());

        }
        catch (IOException ioe){
            ioe.printStackTrace();
        }
        finally{
            try { zos.closeEntry();} catch (IOException e) {}
        }
    }

}

Не работает. Первый файл, который не открывается, означает, что он поврежден, а второй файл пуст.

prem30488 31.08.2016 13:00

Как вы создали zip-файл. Он должен быть без корневой папки и т. д. Лучший способ в Windows - использовать поддержку архивирования TotalCMD. Предлагаемый порядок: 1. Создать docx в MSWord. Откройте zip-архив в TotalCMD с помощью CTRL + PgDown. Удалите document.xml. Нажмите клавишу Backspace и подтвердите изменения в zip-архиве.

Mitja Gustin 31.08.2016 15:06

Я думаю, что выполнял отдельную задачу, которая была выполнена с использованием этого ответа stackoverflow.com/a/17835814/1459174

prem30488 31.08.2016 15:14

Другие вопросы по теме