Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Применяем Apache POI, docx4j и springframework.jdbc

Anna | 2.06.2014 | нет комментариев
Здравствуйте!
Представляю пример простого консольного приложения на Java, которое считывает данные из БД и из файла*.xslx, а после этого создает документ *.docx, заполняя при этом поля слияния (mergefield). В нем применяются библиотеки Apache POI, docx4j и springframework.jdbc. В примере собрана вместе реализация нескольких Зачастую возникающих в процессе автоматизации задач. Допустимо, что он кому-то будет пригоден.

О приложение
Что оно может:

  • Считывать данные из файла формата xslx
  • Извлекать информации из БД (В данном случае применяется Oracle)
  • Формировать файлы формата docx на основе присутствующего фала, заодно добавлять значения в поля слияния

Надобность в данного рода приложении появилась, когда понадобилось вручную формировать некоторое число однотипных документов для их последующей печати и отправки почтой. Собрав вместе разные куски из других своих мелких наработок, возникло это приложение.
Выбор библиотеки Apache POI не стоял, так как теснее реализовывал задачи с ее применением. А вот docx4j применил из-за того, что в ней была вероятность заполнять поля слияния в документах MS Word. Это мне и было необходимо.
На входе мы имеем некоторый файл MS Excel, в котором имеется информация, идентифицирующая заказчиков. Информация о заказчиках не полная. Для извлечения дополнительных данных мы будем обязаны обращаться в базу данных Oracle через jdbc. После этого приложение сформирует файл MS Word по всякому заказчику.

Реализация

  1. Приложение сделано с применением maven. Для начала разберемся с надобными нам зависимостями. Вот что нужно добавить в файл pom.xml
    Dependencies

    <dependency>   
                <groupId>org.apache.poi</groupId>   
                <artifactId>poi</artifactId>   
                <version>3.9</version>   
            </dependency>   
            <dependency>   
                <groupId>org.apache.poi</groupId>   
                <artifactId>poi-ooxml</artifactId>   
                <version>3.9</version>   
            </dependency> 
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>2.5.6</version>
                <type>jar</type>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-dao</artifactId>
                <version>2.0.6</version>
                <type>jar</type>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>2.5.6</version>
                <type>jar</type>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>2.5.6</version>
                <type>jar</type>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>2.5.6</version>
                <type>jar</type>
            </dependency>
            <dependency>
                <groupId>ojdbc</groupId>
                <artifactId>ojdbc</artifactId>
                <version>14</version>
            </dependency>
            <dependency>
                <groupId>org.docx4j</groupId>
                <artifactId>docx4j</artifactId>
                <version>2.8.1</version>
            </dependency>
    
  2. Разглядим класс App — основной класс приложения. В метоже main данного класса легко создается объект класса HelperWord и вызывается его способ createWord()
    Класс App

    public class App 
    {
        public static void main( String[] args )
        {
            HelperWord helper = new HelperWord();
            helper.createWord();
        }
    }
  3. В классе HelperWord мы получаем данные о заказчике, обрабатываем их и создаем файл MS Word.
    Класс HelperWord

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import org.docx4j.openpackaging.exceptions.Docx4JException;
    import org.docx4j.openpackaging.exceptions.InvalidFormatException;
    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
    
    public class HelperWord {
    
        // Объект класса MyDataManager для работы с данными
        private MyDataManager dmg;
        // Данные из фала *.xslx
        private List<HashMap> clientsRows;
        // Добавочные данные из БД
        private List<HashMap> additionalData;
    
        // Инициирует создание файлов MS Word 
        public void createDocs() {
            // Создаем объект класса MyDataManager для работы с данными
            dmg = new MyDataManager();
            try {
                // Извлекаем данные из файла MS Excel
                clientsRows = dmg.getDataBlock();
                // <editor-fold defaultstate="collapsed" desc="Catch clauses">            
            } catch (FileNotFoundException ex) {
                Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                //</editor-fold>   
            }
            // Создаем файл MS Word и заполняем его
            addDataBlock();    
    
        }
    
        // Создает файл MS Word и заполняет его
        private void addDataBlock() {
            int num = 0;
            // Считываем информацию о всяком клменте
            for (HashMap row : clientsRows) {            
                try {
                    num  ;
                    // Извлекаем данные о присутствующем объекте MS Word
                    WordprocessingMLPackage wordMLPackage =
                            WordprocessingMLPackage
                            .load(new File("template.docx"));
                    // Создаем объект для вставки значений в поля слияния
                    List<Map<DataFieldName, String>> data = 
                            new ArrayList<Map<DataFieldName, String>>();
                    // Получаем добавочные данные о заказчике из базы
                    additionalData = dmg.getAddress(row.get("NAME").toString(), 
                            row.get("DOCDATE").toString());
                    // Заполняем значения для полей слияния
                    Map<DataFieldName, String> map = 
                            new HashMap<DataFieldName, String>();
                    map.put(new DataFieldName("NAME"), row.get("NAME").toString());
                    map.put(new DataFieldName("ADDRESS"), 
                            additionalData.get(0).get("ADDRESS").toString());                
                    data.add(map);
                    // Создаем новейший объект MS Word на основе присутствующего и 
                    // значений полей слияния
                    WordprocessingMLPackage output = 
                            MailMerger.getConsolidatedResultCrude(
                            wordMLPackage, data);
                    // Сберегаем объект в файл
                    output.save(new File("T:\\VIPISKI_KK\\Письма\\" 
                              num   ". "   row.get("NAME")   ".docx"));
                    // <editor-fold defaultstate="collapsed" desc="Catch clauses">                 
                } catch (InvalidFormatException ex) {
                    Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                } catch (Docx4JException ex) {
                    Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SQLException ex) {
                    Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(HelperWord.class.getName()).log(Level.SEVERE, null, ex);
                }
                // </editor-fold>    
            }
        }
    }
    

    Именно тут мы заполняем поля слияния в документе, применяя библиотеку docx4j. Вероятно, внимание стоит обратить лишь на классы DataFieldName и MailMerger. Как бы бы, они оба обязаны присутствовать в библиотеке docx4j, впрочем в моей сборке их не оказалось. Следственно они были добавлены в план отдельно. Пару слов об этих классах

    • В классе DataFieldName есть поле name и переопределен способ equals. Это сделано для того, что мы сопоставляли наименования полей слияния в верхнем регистре
    • Класс MailMerger как раз и осуществляет вставку значений в поля слияния документа. Код класса всецело позаимствован с официального сайта docx4j. Вот ссылка
  4. MyDataManager — класс для работы с данными. Он использует библиотеки Apache POI для чтения фала MS Excel и классы springframework.jdbc для работы с БД.
    Класс MyDataManager

    import java.io.*;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import oracle.jdbc.pool.OracleDataSource;
    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
    import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
    
    public class MyDataManager {
    
        public NamedParameterJdbcTemplate namedPar;
    
        private OracleDataSource getDataSource() throws SQLException {
            // Создаем объект источника данных и заполняем значения параметров
            OracleDataSource ods = new OracleDataSource();
            ods.setDriverType("thin");
            ods.setServerName("192.168.x.x");
            ods.setPortNumber();
            ods.setDatabaseName("SID");
            ods.setUser("user");
            ods.setPassword("password");
            return ods;
        }
    
        //Получаем данные из MS Excel
        public List<HashMap> getDataBlock()
                throws FileNotFoundException, IOException {
            ArrayList<HashMap> res = new ArrayList<HashMap>();
            FileInputStream file = new FileInputStream(new File("clients.xlsx"));
            XSSFWorkbook workbook = new XSSFWorkbook(file);
            XSSFSheet sheet = workbook.getSheetAt(0);
    
            Iterator<Row> rowIterator = sheet.iterator();
            // Пропускаю первую строку. В моем случае в ней только заколовки
            if(rowIterator.hasNext()) rowIterator.next();
            //Пробегаемся по каждому строкам
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                HashMap line = new HashMap();
                // В моей структуре файла мне увлекательны только 1-ая и 4-ая строки
                Cell cell = row.getCell(0);
                line.put("NAME", cell.getStringCellValue());
                cell = row.getCell(3);
                line.put("DOCDATE", cell.getStringCellValue());
                res.add(line);
            }
            file.close();
            return res;
        }
    
        //Получаем данные из БД
        public List<HashMap> getAddress(String name, String date) 
                throws SQLException, FileNotFoundException, IOException {
            // Получаем источник данных
            OracleDataSource ds = getDataSource();
            // Считываем запрос
            FileInputStream fins = new FileInputStream("query.txt");
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(fins, "UTF8"));
            String query = "";
            String line = "";
            while ((line = br.readLine()) != null) {
                query  = "\n";
                query  = line;
            }
            // Вставляем значения параметров
            namedPar = new NamedParameterJdbcTemplate(ds);
            MapSqlParameterSource namedParameters = new MapSqlParameterSource();
            namedParameters.addValue("NAME", name);
            namedParameters.addValue("DOCDATE", date);
            // Исполняем запрос и получае итог
            List<HashMap> res = (List<HashMap>) namedPar.query(query,
                    namedParameters, new DataMapper());
            try {
                return res;
            } finally {
                ds.close();
            }
        }
    }
    

Завершение
Вот собственно и все приложение. Безусловно, многон в нем зашито в код (настройки соединения с базой, пути к файлам) и к тому же оно консольное. Дозволено добавить разные проверки и сделать gui. Я этого не делал, так как задача была разовая. Все равно верю, что пост будет кому-то пригоден!
Спасибо за внимание!

 Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB