├── .gitignore ├── Dockerfile ├── LICENSE.txt ├── README.md ├── doc ├── Makefile ├── README.md ├── make.bat ├── requirements.txt └── source │ ├── conf.py │ ├── index.rst │ ├── install │ ├── index.rst │ └── installation.md │ └── quick │ ├── index.rst │ └── tutorial.md ├── docker-compose.yml ├── pom.xml ├── readthedocs.yaml └── src ├── main ├── java │ └── t5750 │ │ └── poi │ │ ├── PoiApplication.java │ │ ├── command │ │ ├── ExcelReplaceDataVO.java │ │ └── ProductForm.java │ │ ├── config │ │ └── RestTemplateConfig.java │ │ ├── controller │ │ ├── ExcelController.java │ │ └── ProductController.java │ │ ├── converter │ │ ├── ProductFormToProduct.java │ │ └── ProductToProductForm.java │ │ ├── domain │ │ ├── Book.java │ │ ├── Product.java │ │ ├── SheetDTO.java │ │ └── Student.java │ │ ├── repository │ │ └── ProductRepository.java │ │ ├── service │ │ ├── ExcelService.java │ │ ├── ProductService.java │ │ └── impl │ │ │ ├── ExcelServiceImpl.java │ │ │ └── ProductServiceImpl.java │ │ └── util │ │ ├── ClassLoaderUtil.java │ │ ├── DateUtil.java │ │ ├── EPlatform.java │ │ ├── ExcelExportUtil.java │ │ ├── ExcelReplaceUtil.java │ │ ├── ExcelTemplateUtil.java │ │ ├── Globals.java │ │ ├── HuExcelUtil.java │ │ └── OSinfo.java └── resources │ ├── application.properties │ ├── doc │ ├── productImport.xls │ ├── replaceTemplate.xls │ ├── template.xls │ └── testRead.xls │ ├── img │ └── tomcat.png │ └── templates │ └── product │ ├── list.html │ ├── productform.html │ └── show.html └── test └── java ├── org └── apache │ └── poi │ └── ss │ └── examples │ └── CalendarDemo.java └── t5750 └── poi ├── TestAll.java ├── TestHutoolPoi.java ├── export ├── TestExcelFormulaDemo.java ├── TestExcelStylingDemo.java ├── TestExportExcel.java ├── TestExportExcel2007.java └── TestWriteExcelDemo.java ├── read ├── TestReadExcel.java └── TestReadExcelDemo.java ├── replace └── TestExcelReplace.java ├── template └── TestTemplate.java └── util └── TestUtil.java /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | 3 | ### STS ### 4 | .apt_generated 5 | .classpath 6 | .factorypath 7 | .project 8 | .settings 9 | .springBeans 10 | .sts4-cache 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | /out/ 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /nbbuild/ 22 | /dist/ 23 | /nbdist/ 24 | /.nb-gradle/ 25 | 26 | classes 27 | **/build 28 | .idea*.zip 29 | ### *.log & *.log.* ### 30 | *.log* 31 | target -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8 2 | EXPOSE 8080 3 | ARG JAR_FILE 4 | ADD target/${JAR_FILE} /poi.jar 5 | ENTRYPOINT ["java", "-jar","/poi.jar"] -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | https://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "{}" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright {yyyy} {name of copyright owner} 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | https://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demos using Apache POI 2 | 3 | [![License](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/T5750/poi-repositories/blob/master/LICENSE.txt) 4 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/T5750/poi-repositories/pulls) 5 | [![GitHub stars](https://img.shields.io/github/stars/T5750/poi-repositories.svg?style=social&label=Stars)](https://github.com/T5750/poi-repositories) 6 | [![GitHub forks](https://img.shields.io/github/forks/T5750/poi-repositories.svg?style=social&label=Fork)](https://github.com/T5750/poi-repositories) 7 | 8 | ## Docs 9 | - [https://poix.readthedocs.io](https://poix.readthedocs.io) 10 | 11 | ## Getting Started 12 | ![](https://s0.wailian.download/2019/07/23/apache-poi-min-min.png) 13 | 14 | Step 1: Download 15 | ``` 16 | git clone https://github.com/T5750/poi-repositories.git 17 | cd poi-repositories 18 | ``` 19 | 20 | Step 2: Start Server 21 | ``` 22 | docker-compose up -d 23 | # or 24 | mvn clean spring-boot:run 25 | ``` 26 | [http://localhost:8080/poi](http://localhost:8080/poi) 27 | 28 | ### Tests 29 | - `TestReadExcel`, `TestReadExcelDemo` 30 | - `TestExportExcel`, `TestExportExcel2007`, `TestWriteExcelDemo` 31 | - `TestTemplate`, `TestExcelReplace` 32 | - `CalendarDemo` 33 | - `TestExcelFormulaDemo`, `TestExcelStylingDemo`, `TestAll` 34 | 35 | ### Runtime Environment 36 | - [Java 8](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 37 | - [Spring Framework 5.x](https://spring.io/projects/spring-framework) 38 | - [Spring Boot 2.x](https://spring.io/projects/spring-boot) 39 | - [Derby 10.x](https://db.apache.org/derby/) 40 | - [Hibernate ORM 5.x](http://hibernate.org/orm) 41 | - [POI 5.x](https://poi.apache.org/download.html) 42 | - [Bootstrap 4.x](https://github.com/twbs/bootstrap) 43 | - [Docker 19.x](https://www.docker.com/) 44 | 45 | ### Classes 46 | 1. **HSSF, XSSF and XSSF classes** 47 | 48 | Apache POI main classes usually start with either **HSSF**, **XSSF** or **SXSSF**. 49 | - **HSSF** – is the POI Project’s pure Java implementation of the Excel ’97(-2007) file format. e.g. [HSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFWorkbook.html), [HSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFSheet.html). 50 | - **XSSF** – is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. e.g. [XSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html), [XSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFSheet.html). 51 | - **SXSSF** (since 3.8-beta3) – is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced, and heap space is limited. e.g. [SXSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFWorkbook.html), [SXSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFSheet.html). SXSSF achieves its **low memory footprint by limiting access to the rows that are within a sliding window**, while XSSF gives access to all rows in the document. 52 | 53 | 2. **Row and Cell** 54 | 55 | Apart from above classes, [Row](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Row.html) and [Cell](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html) are used to interact with a particular row and a particular cell in excel sheet. 56 | 57 | 3. **Style Classes** 58 | 59 | A wide range of classes like [CellStyle](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/CellStyle.html), [BuiltinFormats](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/BuiltinFormats.html), [ComparisonOperator](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ComparisonOperator.html), [ConditionalFormattingRule](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ConditionalFormattingRule.html), [FontFormatting](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/FontFormatting.html), [IndexedColors](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/IndexedColors.html), [PatternFormatting](https://poi.apache.org/apidocs/org/apache/poi/hssf/record/cf/PatternFormatting.html), [SheetConditionalFormatting](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/SheetConditionalFormatting.html) etc. are used when you have to add formatting in a sheet, mostly based on some rules. 60 | 61 | 4. **FormulaEvaluator** 62 | 63 | Another useful class **FormulaEvaluator** is used to evaluate the formula cells in excel sheet. 64 | 65 | ### Write an excel file 66 | 1. Create a workbook 67 | 3. Create a sheet in workbook 68 | 4. Create a row in sheet 69 | 5. Add cells in sheet 70 | 6. Repeat step 3 and 4 to write more data 71 | 72 | ### Read an excel file 73 | 1. Create workbook instance from excel sheet 74 | 3. Get to the desired sheet 75 | 4. Increment row number 76 | 5. iterate over all cells in a row 77 | 6. repeat step 3 and 4 until all data is read 78 | 79 | ## Getting Help 80 | Having trouble with T5750's POI? We’d like to help! 81 | - Ask a question on [CSDN](https://blog.csdn.net/evangel_z/article/details/7332535). 82 | - Report bugs at [https://github.com/T5750/poi/issues](https://github.com/T5750/poi/issues). 83 | 84 | ## Branch 85 | - View POI 3.x branch at [https://github.com/T5750/poi/tree/poi3](https://github.com/T5750/poi/tree/poi3). 86 | - View servlet branch at [https://github.com/T5750/poi/tree/servlet](https://github.com/T5750/poi/tree/servlet). 87 | 88 | ## References 89 | - [Java POI导出EXCEL经典实现 Java导出Excel弹出下载框](https://blog.csdn.net/evangel_z/article/details/7332535) 90 | - [Java POI读取Office excel (2003,2007)及相关jar包](https://blog.csdn.net/evangel_z/article/details/7312050) 91 | - [HSSF and XSSF Examples](http://poi.apache.org/spreadsheet/examples.html) 92 | - [Apache POI – Read and Write Excel File in Java](https://howtodoinjava.com/library/readingwriting-excel-files-in-java-poi-tutorial/) 93 | 94 | ## License 95 | This project is Open Source software released under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html). 96 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | # POI Repositories 2 | 3 | ## POI Repositories RTD 4 | Read the Docs for POI Repositories 5 | - Docs: https://poix.readthedocs.io 6 | - Source: https://github.com/T5750/poi 7 | 8 | ## Runtime Environment 9 | - [Python 3.7.x](https://www.python.org/downloads/) 10 | - [pip 19.0.x](https://github.com/pypa/pip) 11 | - [Sphinx 2.2.x](http://www.sphinx-doc.org/en/master/usage/installation.html) 12 | - [recommonmark](https://github.com/readthedocs/recommonmark) 13 | - [readthedocs.org](https://github.com/readthedocs/readthedocs.org) 14 | - [sphinx_rtd_theme](https://github.com/readthedocs/sphinx_rtd_theme) 15 | - [sphinx-markdown-tables](https://github.com/ryanfox/sphinx-markdown-tables) -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx-markdown-tables 2 | docutils<0.18 3 | recommonmark 4 | sphinx-rtd-theme -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'poi' 23 | copyright = u'2024, T5750' 24 | author = u'T5750' 25 | 26 | # The short X.Y version 27 | version = u'' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'1.0' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = ['sphinx_markdown_tables','recommonmark' 42 | ] 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ['_templates'] 46 | 47 | # The suffix(es) of source filenames. 48 | # You can specify multiple suffix as a list of string: 49 | # 50 | # source_suffix = ['.rst', '.md'] 51 | #source_suffix = '.rst' 52 | source_suffix = { 53 | '.rst': 'restructuredtext', 54 | '.txt': 'markdown', 55 | '.md': 'markdown', 56 | } 57 | 58 | # The master toctree document. 59 | master_doc = 'index' 60 | 61 | # The language for content autogenerated by Sphinx. Refer to documentation 62 | # for a list of supported languages. 63 | # 64 | # This is also used if you do content translation via gettext catalogs. 65 | # Usually you set "language" from the command line for these cases. 66 | language = 'zh_CN' 67 | 68 | # List of patterns, relative to source directory, that match files and 69 | # directories to ignore when looking for source files. 70 | # This pattern also affects html_static_path and html_extra_path. 71 | exclude_patterns = [] 72 | 73 | # The name of the Pygments (syntax highlighting) style to use. 74 | pygments_style = None 75 | 76 | 77 | # -- Options for HTML output ------------------------------------------------- 78 | 79 | # The theme to use for HTML and HTML Help pages. See the documentation for 80 | # a list of builtin themes. 81 | # 82 | #html_theme = 'alabaster' 83 | html_theme = 'sphinx_rtd_theme' 84 | 85 | # Theme options are theme-specific and customize the look and feel of a theme 86 | # further. For a list of options available for each theme, see the 87 | # documentation. 88 | # 89 | # html_theme_options = {} 90 | 91 | # Add any paths that contain custom static files (such as style sheets) here, 92 | # relative to this directory. They are copied after the builtin static files, 93 | # so a file named "default.css" will overwrite the builtin "default.css". 94 | html_static_path = ['_static'] 95 | 96 | # Custom sidebar templates, must be a dictionary that maps document names 97 | # to template names. 98 | # 99 | # The default sidebars (for documents that don't match any pattern) are 100 | # defined by theme itself. Builtin themes are using these templates by 101 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 102 | # 'searchbox.html']``. 103 | # 104 | # html_sidebars = {} 105 | 106 | 107 | # -- Options for HTMLHelp output --------------------------------------------- 108 | 109 | # Output file base name for HTML help builder. 110 | htmlhelp_basename = 'poidoc' 111 | 112 | 113 | # -- Options for LaTeX output ------------------------------------------------ 114 | 115 | latex_elements = { 116 | # The paper size ('letterpaper' or 'a4paper'). 117 | # 118 | # 'papersize': 'letterpaper', 119 | 120 | # The font size ('10pt', '11pt' or '12pt'). 121 | # 122 | # 'pointsize': '10pt', 123 | 124 | # Additional stuff for the LaTeX preamble. 125 | # 126 | # 'preamble': '', 127 | 128 | # Latex figure (float) alignment 129 | # 130 | # 'figure_align': 'htbp', 131 | } 132 | 133 | # Grouping the document tree into LaTeX files. List of tuples 134 | # (source start file, target name, title, 135 | # author, documentclass [howto, manual, or own class]). 136 | latex_documents = [ 137 | (master_doc, 'poi.tex', u'POI Documentation', 138 | u'T5750', 'manual'), 139 | ] 140 | 141 | 142 | # -- Options for manual page output ------------------------------------------ 143 | 144 | # One entry per manual page. List of tuples 145 | # (source start file, name, description, authors, manual section). 146 | man_pages = [ 147 | (master_doc, 'poi', u'POI Documentation', 148 | [author], 1) 149 | ] 150 | 151 | 152 | # -- Options for Texinfo output ---------------------------------------------- 153 | 154 | # Grouping the document tree into Texinfo files. List of tuples 155 | # (source start file, target name, title, author, 156 | # dir menu entry, description, category) 157 | texinfo_documents = [ 158 | (master_doc, 'poi', u'POI Documentation', 159 | author, 'poi', 'One line description of project.', 160 | 'Miscellaneous'), 161 | ] 162 | 163 | 164 | # -- Options for Epub output ------------------------------------------------- 165 | 166 | # Bibliographic Dublin Core info. 167 | epub_title = project 168 | 169 | # The unique identifier of the text. This can be a ISBN number 170 | # or the project homepage. 171 | # 172 | # epub_identifier = '' 173 | 174 | # A unique identification for the text. 175 | # 176 | # epub_uid = '' 177 | 178 | # A list of files that should not be packed into the epub file. 179 | epub_exclude_files = ['search.html'] 180 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. poi documentation master file, created by 2 | sphinx-quickstart on Sat Oct 5 08:38:13 2019. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | POI Repositories 7 | =============================== 8 | Read and Write Excel file using Java and Apache POI, I hope this can help you. 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | :glob: 13 | 14 | install/index 15 | quick/index -------------------------------------------------------------------------------- /doc/source/install/index.rst: -------------------------------------------------------------------------------- 1 | 安装运行 2 | =============================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :numbered: 2 7 | 8 | installation -------------------------------------------------------------------------------- /doc/source/install/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## 下载 4 | - [Java 8](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 5 | - [Maven 3.x](http://maven.apache.org/download.cgi) 6 | - [Git 2.x](https://git-scm.com/downloads) 7 | - [Tomcat 8](https://tomcat.apache.org/download-80.cgi) 8 | 9 | ## 设置 10 | Windows中设置4个环境变量:`JAVA_HOME`、`CLASSPATH`、`M2_HOME`、`PATH` 11 | 12 | ### Java 13 | - `JAVA_HOME`: `path/jdk1.8.0_131` 14 | - `CLASSPATH`: `.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar` 15 | 16 | ### Maven 17 | - `M2_HOME`: `path/apache-maven-3.3.9` 18 | - 或者,设置IntelliJ IDEA 15 -> Settings -> Build Tools -> Maven -> Maven home directory 19 | 20 | ### Path 21 | - `PATH`: `%JAVA_HOME%\bin;%M2_HOME%\bin;%PATH%` 22 | 23 | ### Version 24 | - `java -version` 25 | - `javac -version` 26 | - `mvn -v` 27 | - `git --version` 28 | 29 | ## 运行 30 | ``` 31 | git clone https://github.com/T5750/poi-repositories.git 32 | cd poi-repositories 33 | ``` 34 | 35 | ### Embedded Tomcat 36 | ``` 37 | mvn clean spring-boot:run 38 | ``` 39 | 40 | ### Tomcat 41 | ``` 42 | mvn clean package 43 | ``` 44 | - 复制`target/poi.war`到`path/apache-tomcat-8.5.46/webapps` 45 | - 运行`path/apache-tomcat-8.5.46/bin/startup.bat` 46 | - [http://localhost:8080/poi](http://localhost:8080/poi) 47 | 48 | ### IDE 49 | - `PoiApplication` -------------------------------------------------------------------------------- /doc/source/quick/index.rst: -------------------------------------------------------------------------------- 1 | 快速入门 2 | =============================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :numbered: 2 7 | 8 | tutorial -------------------------------------------------------------------------------- /doc/source/quick/tutorial.md: -------------------------------------------------------------------------------- 1 | # Tutorial 2 | 3 | ## Docs 4 | - [https://poix.readthedocs.io](https://poix.readthedocs.io) 5 | 6 | ## Getting Started 7 | ![](https://s0.wailian.download/2019/07/23/apache-poi-min-min.png) 8 | 9 | Step 1: Download 10 | ``` 11 | git clone https://github.com/T5750/poi-repositories.git 12 | cd poi-repositories 13 | ``` 14 | 15 | Step 2: Start Server 16 | ``` 17 | docker-compose up -d 18 | # or 19 | mvn clean spring-boot:run 20 | ``` 21 | [http://localhost:8080/poi](http://localhost:8080/poi) 22 | 23 | ### Tests 24 | - `TestReadExcel`, `TestReadExcelDemo` 25 | - `TestExportExcel`, `TestExportExcel2007`, `TestWriteExcelDemo` 26 | - `TestTemplate`, `TestExcelReplace` 27 | - `CalendarDemo` 28 | - `TestExcelFormulaDemo`, `TestExcelStylingDemo`, `TestAll` 29 | 30 | ### Runtime Environment 31 | - [Java 8](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 32 | - [Spring Framework 5.x](https://spring.io/projects/spring-framework) 33 | - [Spring Boot 2.x](https://spring.io/projects/spring-boot) 34 | - [Derby 10.x](https://db.apache.org/derby/) 35 | - [Hibernate ORM 5.x](http://hibernate.org/orm) 36 | - [POI 5.x](https://poi.apache.org/download.html) 37 | - [Bootstrap 4.x](https://github.com/twbs/bootstrap) 38 | - [Docker 19.x](https://www.docker.com/) 39 | 40 | ### Classes 41 | 1. **HSSF, XSSF and XSSF classes** 42 | 43 | Apache POI main classes usually start with either **HSSF**, **XSSF** or **SXSSF**. 44 | - **HSSF** – is the POI Project’s pure Java implementation of the Excel ’97(-2007) file format. e.g. [HSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFWorkbook.html), [HSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFSheet.html). 45 | - **XSSF** – is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. e.g. [XSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html), [XSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFSheet.html). 46 | - **SXSSF** (since 3.8-beta3) – is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced, and heap space is limited. e.g. [SXSSFWorkbook](https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFWorkbook.html), [SXSSFSheet](https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFSheet.html). SXSSF achieves its **low memory footprint by limiting access to the rows that are within a sliding window**, while XSSF gives access to all rows in the document. 47 | 48 | 2. **Row and Cell** 49 | 50 | Apart from above classes, [Row](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Row.html) and [Cell](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html) are used to interact with a particular row and a particular cell in excel sheet. 51 | 52 | 3. **Style Classes** 53 | 54 | A wide range of classes like [CellStyle](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/CellStyle.html), [BuiltinFormats](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/BuiltinFormats.html), [ComparisonOperator](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ComparisonOperator.html), [ConditionalFormattingRule](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ConditionalFormattingRule.html), [FontFormatting](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/FontFormatting.html), [IndexedColors](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/IndexedColors.html), [PatternFormatting](https://poi.apache.org/apidocs/org/apache/poi/hssf/record/cf/PatternFormatting.html), [SheetConditionalFormatting](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/SheetConditionalFormatting.html) etc. are used when you have to add formatting in a sheet, mostly based on some rules. 55 | 56 | 4. **FormulaEvaluator** 57 | 58 | Another useful class **FormulaEvaluator** is used to evaluate the formula cells in excel sheet. 59 | 60 | ### Write an excel file 61 | 1. Create a workbook 62 | 3. Create a sheet in workbook 63 | 4. Create a row in sheet 64 | 5. Add cells in sheet 65 | 6. Repeat step 3 and 4 to write more data 66 | 67 | ### Read an excel file 68 | 1. Create workbook instance from excel sheet 69 | 3. Get to the desired sheet 70 | 4. Increment row number 71 | 5. iterate over all cells in a row 72 | 6. repeat step 3 and 4 until all data is read 73 | 74 | ## Getting Help 75 | Having trouble with T5750's POI? We’d like to help! 76 | - Ask a question on [CSDN](https://blog.csdn.net/evangel_z/article/details/7332535). 77 | - Report bugs at [https://github.com/T5750/poi/issues](https://github.com/T5750/poi/issues). 78 | 79 | ## Branch 80 | - View POI 3.x branch at [https://github.com/T5750/poi/tree/poi3](https://github.com/T5750/poi/tree/poi3). 81 | - View servlet branch at [https://github.com/T5750/poi/tree/servlet](https://github.com/T5750/poi/tree/servlet). 82 | 83 | ## References 84 | - [Java POI导出EXCEL经典实现 Java导出Excel弹出下载框](https://blog.csdn.net/evangel_z/article/details/7332535) 85 | - [Java POI读取Office excel (2003,2007)及相关jar包](https://blog.csdn.net/evangel_z/article/details/7312050) 86 | - [HSSF and XSSF Examples](http://poi.apache.org/spreadsheet/examples.html) 87 | - [Apache POI – Read and Write Excel File in Java](https://howtodoinjava.com/library/readingwriting-excel-files-in-java-poi-tutorial/) 88 | 89 | ## License 90 | This project is Open Source software released under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html). -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | poi: 4 | restart: always 5 | image: t5750/poi 6 | container_name: poi 7 | hostname: poi 8 | ports: 9 | - 8080:8080 10 | environment: 11 | TZ: Asia/Shanghai 12 | volumes: 13 | - /etc/localtime:/etc/localtime:ro 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | t5750 7 | poi 8 | ${revision} 9 | Java POI 10 | Java POI 11 | jar 12 | 13 | 1.2 14 | UTF-8 15 | 1.8 16 | 5.2.2 17 | 2.7.1 18 | 5.8.27 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-dependencies 28 | ${spring-boot-version} 29 | pom 30 | import 31 | 32 | 33 | 34 | 35 | 36 | org.apache.poi 37 | poi 38 | ${poi.version} 39 | 40 | 41 | org.apache.poi 42 | poi-ooxml 43 | ${poi.version} 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-web 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-validation 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-test 56 | test 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-data-jpa 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-thymeleaf 65 | 66 | 67 | org.apache.derby 68 | derby 69 | 70 | 71 | cn.hutool 72 | hutool-poi 73 | ${hutool.version} 74 | 75 | 76 | junit 77 | junit 78 | test 79 | 80 | 81 | 82 | ${project.artifactId} 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-compiler-plugin 87 | 3.1 88 | 89 | ${java.version} 90 | ${java.version} 91 | ${project.build.sourceEncoding} 92 | 93 | 94 | 95 | org.springframework.boot 96 | spring-boot-maven-plugin 97 | ${spring-boot-version} 98 | 99 | 100 | 101 | repackage 102 | 103 | 104 | 105 | 106 | 107 | org.apache.maven.plugins 108 | maven-jar-plugin 109 | 3.0.2 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-surefire-plugin 114 | 115 | true 116 | 117 | 118 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: doc/source/conf.py 21 | 22 | # Build documentation with MkDocs 23 | #mkdocs: 24 | # configuration: mkdocs.yml 25 | 26 | # Optionally build your docs in additional formats such as PDF and ePub 27 | formats: [] 28 | 29 | # Optionally set the version of Python and requirements required to build your docs 30 | python: 31 | install: 32 | - requirements: doc/requirements.txt -------------------------------------------------------------------------------- /src/main/java/t5750/poi/PoiApplication.java: -------------------------------------------------------------------------------- 1 | package t5750.poi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 6 | import t5750.poi.util.Globals; 7 | 8 | import java.io.File; 9 | 10 | @SpringBootApplication 11 | public class PoiApplication extends SpringBootServletInitializer { 12 | public static void main(String[] args) { 13 | File file = new File(Globals.DOC_PATH); 14 | if (!file.exists()) { 15 | file.mkdirs(); 16 | } 17 | SpringApplication.run(PoiApplication.class, args); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/command/ExcelReplaceDataVO.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.command; 2 | 3 | /** 4 | * Excel替换内容存储对象 5 | */ 6 | public class ExcelReplaceDataVO { 7 | private int row;// Excel单元格行 8 | private int column;// Excel单元格列 9 | private String key;// 替换的关键字 10 | private String value;// 替换的文本 11 | 12 | public int getRow() { 13 | return row; 14 | } 15 | 16 | public void setRow(int row) { 17 | this.row = row; 18 | } 19 | 20 | public int getColumn() { 21 | return column; 22 | } 23 | 24 | public void setColumn(int column) { 25 | this.column = column; 26 | } 27 | 28 | public String getKey() { 29 | return key; 30 | } 31 | 32 | public void setKey(String key) { 33 | this.key = key; 34 | } 35 | 36 | public String getValue() { 37 | return value; 38 | } 39 | 40 | public void setValue(String value) { 41 | this.value = value; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/command/ProductForm.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.command; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import org.hibernate.validator.constraints.NotBlank; 6 | 7 | public class ProductForm { 8 | private Long id; 9 | @NotBlank 10 | private String description; 11 | private BigDecimal price; 12 | private String imageUrl; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getDescription() { 23 | return description; 24 | } 25 | 26 | public void setDescription(String description) { 27 | this.description = description; 28 | } 29 | 30 | public BigDecimal getPrice() { 31 | return price; 32 | } 33 | 34 | public void setPrice(BigDecimal price) { 35 | this.price = price; 36 | } 37 | 38 | public String getImageUrl() { 39 | return imageUrl; 40 | } 41 | 42 | public void setImageUrl(String imageUrl) { 43 | this.imageUrl = imageUrl; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.client.RestTemplate; 6 | 7 | @Configuration 8 | public class RestTemplateConfig { 9 | @Bean 10 | public RestTemplate getRestTemplate() { 11 | return new RestTemplate(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/controller/ExcelController.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.controller; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.LinkedHashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.core.io.ClassPathResource; 15 | import org.springframework.core.io.Resource; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import t5750.poi.domain.SheetDTO; 19 | import t5750.poi.service.ExcelService; 20 | import t5750.poi.util.Globals; 21 | import t5750.poi.util.HuExcelUtil; 22 | 23 | @RestController 24 | @RequestMapping("/excel") 25 | public class ExcelController { 26 | @Autowired 27 | private ExcelService excelService; 28 | @Autowired 29 | private HttpServletResponse response; 30 | 31 | @RequestMapping(value = "/read/{fileName}", method = RequestMethod.GET) 32 | public List read(@PathVariable String fileName) throws IOException { 33 | Resource resource = new ClassPathResource( 34 | Globals.DOC + File.separator + fileName + Globals.SUFFIX_XLS); 35 | InputStream is = resource.getInputStream(); 36 | List> list = excelService.readExcel(is, 37 | Globals.SUFFIX_XLS); 38 | return list; 39 | } 40 | 41 | @RequestMapping(value = "/export/{fileName}", method = RequestMethod.GET) 42 | public String export(@PathVariable String fileName) throws IOException { 43 | String docsPath = excelService.export2003(fileName, response); 44 | return docsPath; 45 | } 46 | 47 | @RequestMapping(value = "/export2007/{fileName}", method = RequestMethod.GET) 48 | public String export2007(@PathVariable String fileName) throws IOException { 49 | String docsPath = excelService.export2007(fileName, response); 50 | return docsPath; 51 | } 52 | 53 | @RequestMapping(value = "/template/{fileName}", method = RequestMethod.GET) 54 | public String template(@PathVariable String fileName) throws IOException { 55 | String docsPath = excelService.template(fileName, response); 56 | return docsPath; 57 | } 58 | 59 | @RequestMapping(value = "/replace/{fileName}", method = RequestMethod.GET) 60 | public String replace(@PathVariable String fileName) throws IOException { 61 | String docsPath = excelService.replace(fileName, response); 62 | return docsPath; 63 | } 64 | 65 | /** 66 | * 导多个Sheet页 67 | */ 68 | @ResponseBody 69 | @RequestMapping("/multipleSheet") 70 | public void multipleSheet(HttpServletResponse response) { 71 | List> listData = new ArrayList<>(); 72 | Map map = new LinkedHashMap<>(); 73 | map.put("store_name", "客户名称"); 74 | map.put("store_out_trade_no", "客户编码"); 75 | map.put("store_contract_year", "年份"); 76 | List arrayList = new ArrayList<>(); 77 | arrayList.add(new SheetDTO("客户信息", map, listData)); 78 | arrayList.add(new SheetDTO("关联客户信息", map, listData)); 79 | arrayList.add(new SheetDTO("重要负责人信息", map, listData)); 80 | HuExcelUtil.exportExcel(response, arrayList, "multipleSheet"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.Model; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | 15 | import t5750.poi.command.ProductForm; 16 | import t5750.poi.converter.ProductToProductForm; 17 | import t5750.poi.domain.Product; 18 | import t5750.poi.service.ProductService; 19 | 20 | @Controller 21 | public class ProductController { 22 | private ProductService productService; 23 | private ProductToProductForm productToProductForm; 24 | 25 | @Autowired 26 | public void setProductToProductForm( 27 | ProductToProductForm productToProductForm) { 28 | this.productToProductForm = productToProductForm; 29 | } 30 | 31 | @Autowired 32 | public void setProductService(ProductService productService) { 33 | this.productService = productService; 34 | } 35 | 36 | @RequestMapping("/") 37 | public String redirToList() { 38 | return "redirect:/product/list"; 39 | } 40 | 41 | @RequestMapping({ "/product/list", "/product" }) 42 | public String listProducts(Model model) { 43 | model.addAttribute("products", productService.listAll()); 44 | return "product/list"; 45 | } 46 | 47 | @RequestMapping("/product/show/{id}") 48 | public String getProduct(@PathVariable String id, Model model) { 49 | model.addAttribute("product", productService.getById(Long.valueOf(id))); 50 | return "product/show"; 51 | } 52 | 53 | @RequestMapping("product/edit/{id}") 54 | public String edit(@PathVariable String id, Model model) { 55 | Product product = productService.getById(Long.valueOf(id)); 56 | ProductForm productForm = productToProductForm.convert(product); 57 | model.addAttribute("productForm", productForm); 58 | return "product/productform"; 59 | } 60 | 61 | @RequestMapping("/product/new") 62 | public String newProduct(Model model) { 63 | model.addAttribute("productForm", new ProductForm()); 64 | return "product/productform"; 65 | } 66 | 67 | @RequestMapping(value = "/product", method = RequestMethod.POST) 68 | public String saveOrUpdateProduct(@Valid ProductForm productForm, 69 | BindingResult bindingResult) { 70 | if (bindingResult.hasErrors()) { 71 | return "product/productform"; 72 | } 73 | Product savedProduct = productService 74 | .saveOrUpdateProductForm(productForm); 75 | return "redirect:/product/show/" + savedProduct.getId(); 76 | } 77 | 78 | @RequestMapping("/product/delete/{id}") 79 | public String delete(@PathVariable String id) { 80 | productService.delete(Long.valueOf(id)); 81 | return "redirect:/product/list"; 82 | } 83 | 84 | @RequestMapping("/product/export") 85 | public void export(HttpServletResponse response) { 86 | // java.lang.IllegalStateException: getOutputStream() has already been 87 | // called for this response 88 | // https://stackoverflow.com/questions/30560360/i-am-getting-an-exception-java-lang-illegalstateexception-getoutputstream-ha 89 | productService.export(response); 90 | } 91 | 92 | @RequestMapping("/product/excelImport") 93 | public String excelImport(HttpServletRequest request) { 94 | productService.excelImport(request); 95 | return "redirect:/product/list"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/converter/ProductFormToProduct.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.util.StringUtils; 6 | 7 | import t5750.poi.command.ProductForm; 8 | import t5750.poi.domain.Product; 9 | 10 | @Component 11 | public class ProductFormToProduct implements Converter { 12 | @Override 13 | public Product convert(ProductForm productForm) { 14 | Product product = new Product(); 15 | if (productForm.getId() != null 16 | && !StringUtils.isEmpty(productForm.getId())) { 17 | product.setId(new Long(productForm.getId())); 18 | } 19 | product.setDescription(productForm.getDescription()); 20 | product.setPrice(productForm.getPrice()); 21 | product.setImageUrl(productForm.getImageUrl()); 22 | return product; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/converter/ProductToProductForm.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import org.springframework.stereotype.Component; 5 | 6 | import t5750.poi.command.ProductForm; 7 | import t5750.poi.domain.Product; 8 | 9 | @Component 10 | public class ProductToProductForm implements Converter { 11 | @Override 12 | public ProductForm convert(Product product) { 13 | ProductForm productForm = new ProductForm(); 14 | productForm.setId(product.getId()); 15 | productForm.setDescription(product.getDescription()); 16 | productForm.setPrice(product.getPrice()); 17 | productForm.setImageUrl(product.getImageUrl()); 18 | return productForm; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/domain/Book.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.domain; 2 | 3 | public class Book { 4 | private Integer bookId; 5 | private String name; 6 | private String author; 7 | private Float price; 8 | private String isbn; 9 | private String pubName; 10 | private byte[] preface; 11 | 12 | public Book() { 13 | } 14 | 15 | public Book(Integer bookId, String name, String author, Float price, 16 | String isbn, String pubName, byte[] preface) { 17 | this.bookId = bookId; 18 | this.name = name; 19 | this.author = author; 20 | this.price = price; 21 | this.isbn = isbn; 22 | this.pubName = pubName; 23 | this.preface = preface; 24 | } 25 | 26 | public Integer getBookId() { 27 | return bookId; 28 | } 29 | 30 | public void setBookId(Integer bookId) { 31 | this.bookId = bookId; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getAuthor() { 43 | return author; 44 | } 45 | 46 | public void setAuthor(String author) { 47 | this.author = author; 48 | } 49 | 50 | public Float getPrice() { 51 | return price; 52 | } 53 | 54 | public void setPrice(Float price) { 55 | this.price = price; 56 | } 57 | 58 | public String getIsbn() { 59 | return isbn; 60 | } 61 | 62 | public void setIsbn(String isbn) { 63 | this.isbn = isbn; 64 | } 65 | 66 | public String getPubName() { 67 | return pubName; 68 | } 69 | 70 | public void setPubName(String pubName) { 71 | this.pubName = pubName; 72 | } 73 | 74 | public byte[] getPreface() { 75 | return preface; 76 | } 77 | 78 | public void setPreface(byte[] preface) { 79 | this.preface = preface; 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/domain/Product.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.domain; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | 8 | @Entity 9 | public class Product { 10 | @javax.persistence.Id 11 | @GeneratedValue 12 | private Long id; 13 | private String description; 14 | private BigDecimal price; 15 | private String imageUrl; 16 | 17 | public Long getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Long id) { 22 | this.id = id; 23 | } 24 | 25 | public String getDescription() { 26 | return description; 27 | } 28 | 29 | public void setDescription(String description) { 30 | this.description = description; 31 | } 32 | 33 | public BigDecimal getPrice() { 34 | return price; 35 | } 36 | 37 | public void setPrice(BigDecimal price) { 38 | this.price = price; 39 | } 40 | 41 | public String getImageUrl() { 42 | return imageUrl; 43 | } 44 | 45 | public void setImageUrl(String imageUrl) { 46 | this.imageUrl = imageUrl; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/domain/SheetDTO.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.domain; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Excel - Sheet页 10 | */ 11 | public class SheetDTO implements Serializable { 12 | private static final long serialVersionUID = 1L; 13 | /** 14 | * sheet页名称 15 | */ 16 | private String sheetName; 17 | /** 18 | * 字段和别名,如果使用这个,properties 和 titles可以不用处理 Map<字段, 别名> 如:Map<"name", "姓名"> 19 | */ 20 | private Map fieldAndAlias; 21 | /** 22 | * 列宽
23 | * 设置列宽时必须每个字段都设置才生效(columnWidth.size = fieldAndAlias.size) 24 | */ 25 | private List columnWidth; 26 | /** 27 | * 数据集 28 | */ 29 | private Collection collection; 30 | 31 | public SheetDTO() { 32 | } 33 | 34 | /** 35 | * @param sheetName 36 | * sheet页名称 37 | * @param fieldAndAlias 38 | * 字段和别名 39 | * @param collection 40 | * 数据集 41 | */ 42 | public SheetDTO(String sheetName, Map fieldAndAlias, 43 | Collection collection) { 44 | super(); 45 | this.sheetName = sheetName; 46 | this.fieldAndAlias = fieldAndAlias; 47 | this.collection = collection; 48 | } 49 | 50 | public String getSheetName() { 51 | return sheetName; 52 | } 53 | 54 | public void setSheetName(String sheetName) { 55 | this.sheetName = sheetName; 56 | } 57 | 58 | public Map getFieldAndAlias() { 59 | return fieldAndAlias; 60 | } 61 | 62 | public void setFieldAndAlias(Map fieldAndAlias) { 63 | this.fieldAndAlias = fieldAndAlias; 64 | } 65 | 66 | public List getColumnWidth() { 67 | return this.columnWidth; 68 | } 69 | 70 | public void setColumnWidth(List columnWidth) { 71 | this.columnWidth = columnWidth; 72 | } 73 | 74 | public Collection getCollection() { 75 | return collection; 76 | } 77 | 78 | public void setCollection(Collection collection) { 79 | this.collection = collection; 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/domain/Student.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.domain; 2 | 3 | import java.util.Date; 4 | 5 | public class Student { 6 | private Long id; 7 | private String name; 8 | private Integer age; 9 | private Boolean sex; 10 | private Date birthday; 11 | 12 | public Student() { 13 | } 14 | 15 | public Student(Long id, String name, Integer age, Boolean sex, Date birthday) { 16 | this.id = id; 17 | this.name = name; 18 | this.age = age; 19 | this.sex = sex; 20 | this.birthday = birthday; 21 | } 22 | 23 | public Long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(Long id) { 28 | this.id = id; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | public Integer getAge() { 40 | return age; 41 | } 42 | 43 | public void setAge(Integer age) { 44 | this.age = age; 45 | } 46 | 47 | public Boolean getSex() { 48 | return sex; 49 | } 50 | 51 | public void setSex(Boolean sex) { 52 | this.sex = sex; 53 | } 54 | 55 | public Date getBirthday() { 56 | return birthday; 57 | } 58 | 59 | public void setBirthday(Date birthday) { 60 | this.birthday = birthday; 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/repository/ProductRepository.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import t5750.poi.domain.Product; 6 | 7 | public interface ProductRepository extends CrudRepository { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/service/ExcelService.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.service; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.List; 7 | 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | public interface ExcelService { 11 | List> readExcel(File file) throws IOException; 12 | 13 | List> readExcel(InputStream is, String suffix) 14 | throws IOException; 15 | 16 | void download(String filename, InputStream is, HttpServletResponse response) 17 | throws IOException; 18 | 19 | void download(String filename, String path, HttpServletResponse response) 20 | throws IOException; 21 | 22 | String export2003(String fileName, HttpServletResponse response) 23 | throws IOException; 24 | 25 | String export2007(String fileName, HttpServletResponse response) 26 | throws IOException; 27 | 28 | String template(String fileName, HttpServletResponse response) 29 | throws IOException; 30 | 31 | String replace(String fileName, HttpServletResponse response) 32 | throws IOException; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import t5750.poi.command.ProductForm; 9 | import t5750.poi.domain.Product; 10 | 11 | public interface ProductService { 12 | List listAll(); 13 | 14 | Product getById(Long id); 15 | 16 | Product saveOrUpdate(Product product); 17 | 18 | void delete(Long id); 19 | 20 | Product saveOrUpdateProductForm(ProductForm productForm); 21 | 22 | List export(HttpServletResponse response); 23 | 24 | List excelImport(HttpServletRequest request); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/service/impl/ExcelServiceImpl.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.service.impl; 2 | 3 | import java.io.*; 4 | import java.text.DecimalFormat; 5 | import java.text.SimpleDateFormat; 6 | import java.util.*; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.apache.poi.hssf.usermodel.HSSFCell; 10 | import org.apache.poi.hssf.usermodel.HSSFRow; 11 | import org.apache.poi.hssf.usermodel.HSSFSheet; 12 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 13 | import org.apache.poi.xssf.usermodel.XSSFCell; 14 | import org.apache.poi.xssf.usermodel.XSSFRow; 15 | import org.apache.poi.xssf.usermodel.XSSFSheet; 16 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 17 | import org.springframework.core.io.ClassPathResource; 18 | import org.springframework.core.io.Resource; 19 | import org.springframework.stereotype.Service; 20 | import t5750.poi.command.ExcelReplaceDataVO; 21 | import t5750.poi.service.ExcelService; 22 | import t5750.poi.util.*; 23 | 24 | @Service 25 | public class ExcelServiceImpl implements ExcelService { 26 | /** 27 | * 对外提供读取excel 的方法 28 | */ 29 | @Override 30 | public List> readExcel(File file) throws IOException { 31 | String fileName = file.getName(); 32 | String extension = fileName.lastIndexOf(".") == -1 ? "" 33 | : fileName.substring(fileName.lastIndexOf(".") + 1); 34 | if ("xls".equals(extension)) { 35 | return readExcel2003(file); 36 | } else if ("xlsx".equals(extension)) { 37 | return readExcel2007(file); 38 | } else { 39 | throw new IOException("不支持的文件类型"); 40 | } 41 | } 42 | 43 | @Override 44 | public List> readExcel(InputStream is, String suffix) 45 | throws IOException { 46 | if (Globals.SUFFIX_XLS.equals(suffix)) { 47 | return readExcel2003(is); 48 | } else if (Globals.SUFFIX_XLSX.equals(suffix)) { 49 | return readExcel2007(is); 50 | } else { 51 | throw new IOException("不支持的文件类型"); 52 | } 53 | } 54 | 55 | /** 56 | * 读取 office 2003 excel 57 | */ 58 | private List> readExcel2003(InputStream is) 59 | throws IOException { 60 | List> list = new LinkedList>(); 61 | HSSFWorkbook hwb = new HSSFWorkbook(is); 62 | HSSFSheet sheet = hwb.getSheetAt(0); 63 | Object value = null; 64 | HSSFRow row = null; 65 | HSSFCell cell = null; 66 | int counter = 0; 67 | for (int i = sheet.getFirstRowNum(); counter < sheet 68 | .getPhysicalNumberOfRows(); i++) { 69 | row = sheet.getRow(i); 70 | if (row == null) { 71 | continue; 72 | } else { 73 | counter++; 74 | } 75 | List linked = new LinkedList(); 76 | for (int j = row.getFirstCellNum(); j <= row 77 | .getLastCellNum(); j++) { 78 | cell = row.getCell(j); 79 | if (cell == null) { 80 | continue; 81 | } 82 | DecimalFormat df = new DecimalFormat("0");// 格式化 number String 83 | // 字符 84 | SimpleDateFormat sdf = new SimpleDateFormat( 85 | "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串 86 | DecimalFormat nf = new DecimalFormat("0.00");// 格式化数字 87 | switch (cell.getCellType()) { 88 | case STRING: 89 | value = cell.getStringCellValue(); 90 | System.out.println(i + "行" + j + " 列 is String type" 91 | + "\tValue:" + value); 92 | break; 93 | case NUMERIC: 94 | if ("@".equals(cell.getCellStyle().getDataFormatString())) { 95 | value = df.format(cell.getNumericCellValue()); 96 | } else if ("General".equals( 97 | cell.getCellStyle().getDataFormatString())) { 98 | value = nf.format(cell.getNumericCellValue()); 99 | } else { 100 | value = sdf.format(org.apache.poi.ss.usermodel.DateUtil 101 | .getJavaDate(cell.getNumericCellValue())); 102 | } 103 | System.out.println( 104 | i + "行" + j + " 列 is Number type ; DateFormt:" 105 | + cell.getCellStyle().getDataFormatString() 106 | + "\tValue:" + value); 107 | break; 108 | case BOOLEAN: 109 | value = cell.getBooleanCellValue(); 110 | System.out.println(i + "行" + j + " 列 is Boolean type" 111 | + "\tValue:" + value); 112 | break; 113 | case BLANK: 114 | value = ""; 115 | System.out.println(i + "行" + j + " 列 is Blank type" 116 | + "\tValue:" + value); 117 | break; 118 | default: 119 | value = cell.toString(); 120 | System.out.println(i + "行" + j + " 列 is default type" 121 | + "\tValue:" + value); 122 | } 123 | if (value == null || "".equals(value)) { 124 | continue; 125 | } 126 | linked.add(value); 127 | } 128 | list.add(linked); 129 | } 130 | return list; 131 | } 132 | 133 | private List> readExcel2003(File file) throws IOException { 134 | return readExcel2003(new FileInputStream(file)); 135 | } 136 | 137 | /** 138 | * 读取Office 2007 excel 139 | */ 140 | private List> readExcel2007(InputStream is) 141 | throws IOException { 142 | List> list = new LinkedList>(); 143 | // 构造 XSSFWorkbook 对象,strPath 传入文件路径 144 | XSSFWorkbook xwb = new XSSFWorkbook(is); 145 | // 读取第一章表格内容 146 | XSSFSheet sheet = xwb.getSheetAt(0); 147 | Object value = null; 148 | XSSFRow row = null; 149 | XSSFCell cell = null; 150 | int counter = 0; 151 | for (int i = sheet.getFirstRowNum(); counter < sheet 152 | .getPhysicalNumberOfRows(); i++) { 153 | row = sheet.getRow(i); 154 | if (row == null) { 155 | continue; 156 | } else { 157 | counter++; 158 | } 159 | List linked = new LinkedList(); 160 | for (int j = row.getFirstCellNum(); j <= row 161 | .getLastCellNum(); j++) { 162 | cell = row.getCell(j); 163 | if (cell == null) { 164 | continue; 165 | } 166 | DecimalFormat df = new DecimalFormat("0");// 格式化 number String 167 | // 字符 168 | SimpleDateFormat sdf = new SimpleDateFormat( 169 | "yyyy-MM-dd HH:mm:ss");// 格式化日期字符串 170 | DecimalFormat nf = new DecimalFormat("0.00");// 格式化数字 171 | switch (cell.getCellType()) { 172 | case STRING: 173 | System.out.println(i + "行" + j + " 列 is String type"); 174 | value = cell.getStringCellValue(); 175 | break; 176 | case NUMERIC: 177 | System.out.println(i + "行" + j 178 | + " 列 is Number type ; DateFormt:" 179 | + cell.getCellStyle().getDataFormatString()); 180 | if ("@".equals(cell.getCellStyle().getDataFormatString())) { 181 | value = df.format(cell.getNumericCellValue()); 182 | } else if ("General".equals( 183 | cell.getCellStyle().getDataFormatString())) { 184 | value = nf.format(cell.getNumericCellValue()); 185 | } else { 186 | value = sdf.format(org.apache.poi.ss.usermodel.DateUtil 187 | .getJavaDate(cell.getNumericCellValue())); 188 | } 189 | break; 190 | case BOOLEAN: 191 | System.out.println(i + "行" + j + " 列 is Boolean type"); 192 | value = cell.getBooleanCellValue(); 193 | break; 194 | case BLANK: 195 | System.out.println(i + "行" + j + " 列 is Blank type"); 196 | value = ""; 197 | break; 198 | default: 199 | System.out.println(i + "行" + j + " 列 is default type"); 200 | value = cell.toString(); 201 | } 202 | if (value == null || "".equals(value)) { 203 | continue; 204 | } 205 | linked.add(value); 206 | } 207 | list.add(linked); 208 | } 209 | return list; 210 | } 211 | 212 | private List> readExcel2007(File file) throws IOException { 213 | return readExcel2007(new FileInputStream(file)); 214 | } 215 | 216 | @Override 217 | public void download(String filename, InputStream is, 218 | HttpServletResponse response) throws IOException { 219 | // path是指欲下载的文件的路径。 220 | // File file = new File(path); 221 | // 取得文件名。 222 | // String filename = file.getName(); 223 | // 以流的形式下载文件。 224 | InputStream fis = new BufferedInputStream(is); 225 | byte[] buffer = new byte[fis.available()]; 226 | fis.read(buffer); 227 | fis.close(); 228 | // 清空response 229 | response.reset(); 230 | // 设置response的Header 231 | response.addHeader("Content-Disposition", "attachment;filename=" 232 | + new String(filename.getBytes(), "ISO-8859-1")); 233 | // response.addHeader("Content-Length", "" + file.length()); 234 | OutputStream toClient = new BufferedOutputStream( 235 | response.getOutputStream()); 236 | response.setContentType("application/vnd.ms-excel;charset=gb2312"); 237 | toClient.write(buffer); 238 | toClient.flush(); 239 | toClient.close(); 240 | } 241 | 242 | @Override 243 | public void download(String filename, String path, 244 | HttpServletResponse response) throws IOException { 245 | download(filename, new FileInputStream(path), response); 246 | } 247 | 248 | @Override 249 | public String export2003(String fileName, HttpServletResponse response) 250 | throws IOException { 251 | String docsPath; 252 | String filename = fileName + Globals.SUFFIX_XLS; 253 | Resource resource = new ClassPathResource( 254 | Globals.DOC + File.separator + fileName + Globals.SUFFIX_XLS); 255 | if (resource.exists()) { 256 | docsPath = resource.getFile().getPath(); 257 | } else { 258 | String imagesPath = Globals.IMG + File.separator + "tomcat" 259 | + Globals.SUFFIX_PNG; 260 | ExcelExportUtil.export2003(imagesPath, Globals.DOC_PATH); 261 | docsPath = Globals.DOC_PATH + File.separator + Globals.EXPORT_BOOK; 262 | filename = Globals.EXPORT_BOOK; 263 | } 264 | download(filename, docsPath, response); 265 | return docsPath; 266 | } 267 | 268 | @Override 269 | public String export2007(String fileName, HttpServletResponse response) 270 | throws IOException { 271 | String filePath = Globals.DOC_PATH + File.separator 272 | + Globals.EXPORT_2007; 273 | ExcelExportUtil.export2007(filePath); 274 | download(Globals.EXPORT_2007, filePath, response); 275 | return filePath; 276 | } 277 | 278 | @Override 279 | public String template(String fileName, HttpServletResponse response) 280 | throws IOException { 281 | Resource resource = new ClassPathResource( 282 | Globals.DOC + File.separator + fileName + Globals.SUFFIX_XLS); 283 | InputStream is = resource.getInputStream(); 284 | String exportFileName = fileName + System.currentTimeMillis() 285 | + Globals.SUFFIX_XLS;// 导出Excel文件名 286 | String exportFilePath = Globals.DOC_PATH + File.separator 287 | + exportFileName; 288 | ExcelTemplateUtil excel = ExcelTemplateUtil.getInstance() 289 | .readTemplatePath(is); 290 | for (int i = 0; i < 5; i++) { 291 | excel.creatNewRow(); 292 | excel.createNewCol("Col" + i); 293 | excel.createNewCol(i); 294 | excel.createNewCol(i); 295 | } 296 | Map datas = new HashMap(); 297 | datas.put("title", "POI Repositories"); 298 | datas.put("content", "the Java API for Microsoft Documents"); 299 | datas.put("date", DateUtil.format(new Date())); 300 | excel.replaceFind(datas); 301 | excel.insertSer(); 302 | excel.writeToFile(exportFilePath); 303 | download(exportFileName, exportFilePath, response); 304 | return exportFilePath; 305 | } 306 | 307 | @Override 308 | public String replace(String fileName, HttpServletResponse response) 309 | throws IOException { 310 | Resource resource = new ClassPathResource( 311 | Globals.DOC + File.separator + fileName + Globals.SUFFIX_XLS); 312 | String exportFileName = fileName + System.currentTimeMillis() 313 | + Globals.SUFFIX_XLS;// 导出Excel文件名 314 | String exportFilePath = Globals.DOC_PATH + File.separator 315 | + exportFileName; 316 | List datas = new ArrayList(); 317 | // 找到第14行第2列的company,用"XXX有限公司"替换掉company 318 | ExcelReplaceDataVO voCompany = new ExcelReplaceDataVO(); 319 | voCompany.setRow(13); 320 | voCompany.setColumn(1); 321 | voCompany.setKey("company"); 322 | voCompany.setValue("XXX有限公司"); 323 | // 找到第5行第2列的content,用"aa替换的内容aa"替换掉content 324 | ExcelReplaceDataVO voContent = new ExcelReplaceDataVO(); 325 | voContent.setRow(4); 326 | voContent.setColumn(1); 327 | voContent.setKey("content"); 328 | voContent.setValue("替换的内容"); 329 | datas.add(voCompany); 330 | datas.add(voContent); 331 | InputStream is = resource.getInputStream(); 332 | ExcelReplaceUtil.replaceModel(datas, is, exportFilePath); 333 | download(exportFileName, exportFilePath, response); 334 | return exportFilePath; 335 | } 336 | } 337 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/service/impl/ProductServiceImpl.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.service.impl; 2 | 3 | import java.io.*; 4 | import java.math.BigDecimal; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.http.HttpEntity; 14 | import org.springframework.http.HttpHeaders; 15 | import org.springframework.http.HttpMethod; 16 | import org.springframework.http.MediaType; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.web.client.RestTemplate; 19 | 20 | import t5750.poi.command.ProductForm; 21 | import t5750.poi.converter.ProductFormToProduct; 22 | import t5750.poi.domain.Product; 23 | import t5750.poi.repository.ProductRepository; 24 | import t5750.poi.service.ExcelService; 25 | import t5750.poi.service.ProductService; 26 | import t5750.poi.util.ExcelExportUtil; 27 | import t5750.poi.util.Globals; 28 | 29 | @Service 30 | public class ProductServiceImpl implements ProductService { 31 | private ProductRepository productRepository; 32 | private ProductFormToProduct productFormToProduct; 33 | @Autowired 34 | private ExcelService excelService; 35 | @Autowired 36 | RestTemplate restTemplate; 37 | 38 | @Autowired 39 | public ProductServiceImpl(ProductRepository productRepository, 40 | ProductFormToProduct productFormToProduct) { 41 | this.productRepository = productRepository; 42 | this.productFormToProduct = productFormToProduct; 43 | } 44 | 45 | @Override 46 | public List listAll() { 47 | List products = new ArrayList<>(); 48 | productRepository.findAll().forEach(products::add); // fun with Java 8 49 | return products; 50 | } 51 | 52 | @Override 53 | public Product getById(Long id) { 54 | return productRepository.findById(id).get(); 55 | } 56 | 57 | @Override 58 | public Product saveOrUpdate(Product product) { 59 | productRepository.save(product); 60 | return product; 61 | } 62 | 63 | @Override 64 | public void delete(Long id) { 65 | productRepository.deleteById(id); 66 | } 67 | 68 | @Override 69 | public Product saveOrUpdateProductForm(ProductForm productForm) { 70 | Product savedProduct = saveOrUpdate( 71 | productFormToProduct.convert(productForm)); 72 | System.out.println("Saved Product Id: " + savedProduct.getId()); 73 | return savedProduct; 74 | } 75 | 76 | @Override 77 | public List export(HttpServletResponse response) { 78 | List products = listAll(); 79 | ExcelExportUtil ex = new ExcelExportUtil(); 80 | String[] headers = { "Id", "Description", "Price", "Image URL" }; 81 | String docsPath = Globals.DOC_PATH + File.separator 82 | + Globals.EXPORT_PRODUCT; 83 | try { 84 | OutputStream out = new FileOutputStream(docsPath); 85 | ex.exportExcel(headers, products, out); 86 | out.close(); 87 | excelService.download(Globals.EXPORT_PRODUCT, docsPath, response); 88 | } catch (FileNotFoundException e) { 89 | e.printStackTrace(); 90 | } catch (IOException e) { 91 | e.printStackTrace(); 92 | } 93 | return products; 94 | } 95 | 96 | @Override 97 | public List excelImport(HttpServletRequest request) { 98 | HttpHeaders headers = new HttpHeaders(); 99 | headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); 100 | HttpEntity entity = new HttpEntity(headers); 101 | List> list = restTemplate.exchange( 102 | Globals.getBasePath(request) + "excel/read/productImport", 103 | HttpMethod.GET, entity, List.class).getBody(); 104 | for (int i = 1; i < list.size(); i++) { 105 | List objList = list.get(i); 106 | Long id = Long.valueOf(objList.get(0).toString()); 107 | boolean flag = productRepository.existsById(id); 108 | if (!flag) { 109 | Product product = new Product(); 110 | product.setId(id); 111 | if (null != objList.get(1)) { 112 | product.setDescription(objList.get(1).toString()); 113 | } 114 | if (objList.size() > 2 && null != objList.get(2)) { 115 | product.setPrice(new BigDecimal(objList.get(2).toString())); 116 | } 117 | if (objList.size() > 3 && null != objList.get(3)) { 118 | product.setImageUrl(objList.get(3).toString()); 119 | } 120 | saveOrUpdate(product); 121 | } else { 122 | } 123 | } 124 | return list; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/ClassLoaderUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.File; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.net.URLDecoder; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * ClassLoaderUtil 13 | */ 14 | public final class ClassLoaderUtil { 15 | protected static final Logger LOGGER = LoggerFactory 16 | .getLogger(ClassLoaderUtil.class); 17 | // class path 18 | private static String classPath = ""; 19 | // loader 20 | private static ClassLoader loader = Thread.currentThread() 21 | .getContextClassLoader(); 22 | 23 | private ClassLoaderUtil() { 24 | } 25 | 26 | // 27 | // get class path 28 | // 29 | static { 30 | if (loader == null) { 31 | LOGGER.info("using system class loader!"); 32 | loader = ClassLoader.getSystemClassLoader(); 33 | } 34 | try { 35 | URL url = loader.getResource(""); 36 | // get class path 37 | File f = new File(url.toURI()); 38 | classPath = f.getAbsolutePath(); 39 | classPath = URLDecoder.decode(classPath, "utf-8"); 40 | // 如果是jar包内的,则返回当前路径 41 | if (classPath.contains(".jar!")) { 42 | LOGGER.warn("using config file inline jar!" + classPath); 43 | classPath = System.getProperty("user.dir"); 44 | // 45 | addCurrentWorkingDir2Classpath(classPath); 46 | } 47 | } catch (Exception e) { 48 | LOGGER.warn("cannot get classpath using getResource(), now using user.dir"); 49 | classPath = System.getProperty("user.dir"); 50 | // 51 | addCurrentWorkingDir2Classpath(classPath); 52 | } 53 | LOGGER.info("classpath: {}", classPath); 54 | } 55 | 56 | /** 57 | * only support 1.7 or higher 58 | * http://stackoverflow.com/questions/252893/how-do 59 | * -you-change-the-classpath-within-java 60 | */ 61 | private static void addCurrentWorkingDir2Classpath(String path2Added) { 62 | // Add the conf dir to the classpath 63 | // Chain the current thread classloader 64 | URLClassLoader urlClassLoader; 65 | try { 66 | urlClassLoader = new URLClassLoader( 67 | new URL[] { new File(path2Added).toURI().toURL() }, loader); 68 | // Replace the thread classloader - assumes 69 | // you have permissions to do so 70 | Thread.currentThread().setContextClassLoader(urlClassLoader); 71 | } catch (Exception e) { 72 | LOGGER.warn(e.toString()); 73 | } 74 | } 75 | 76 | public static String getClassPath() { 77 | return classPath; 78 | } 79 | 80 | public static ClassLoader getLoader() { 81 | return loader; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | /** 7 | * 日期处理 8 | */ 9 | public class DateUtil { 10 | /** 时间格式(yyyy-MM-dd) */ 11 | public final static String DATE_PATTERN = "yyyy-MM-dd"; 12 | /** 时间格式(yyyy-MM-dd HH:mm:ss) */ 13 | public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; 14 | 15 | public static String format(Date date) { 16 | return format(date, DATE_PATTERN); 17 | } 18 | 19 | public static String format(Date date, String pattern) { 20 | if (date != null) { 21 | SimpleDateFormat df = new SimpleDateFormat(pattern); 22 | return df.format(date); 23 | } 24 | return null; 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/EPlatform.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | public enum EPlatform { 4 | Any("any"), Linux("Linux"), Mac_OS("Mac OS"), Mac_OS_X("Mac OS X"), Windows( 5 | "Windows"), OS2("OS/2"), Solaris("Solaris"), SunOS("SunOS"), MPEiX( 6 | "MPE/iX"), HP_UX("HP-UX"), AIX("AIX"), OS390("OS/390"), FreeBSD( 7 | "FreeBSD"), Irix("Irix"), Digital_Unix("Digital Unix"), NetWare_411( 8 | "NetWare"), OSF1("OSF1"), OpenVMS("OpenVMS"), Others("Others"); 9 | private EPlatform(String desc) { 10 | this.description = desc; 11 | } 12 | 13 | public String toString() { 14 | return description; 15 | } 16 | 17 | private String description; 18 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/ExcelExportUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.*; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | import java.text.SimpleDateFormat; 8 | import java.util.*; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | import org.apache.poi.hssf.usermodel.*; 13 | import org.apache.poi.hssf.util.HSSFColor; 14 | import org.apache.poi.ss.usermodel.*; 15 | import org.apache.poi.xssf.usermodel.XSSFRow; 16 | import org.apache.poi.xssf.usermodel.XSSFSheet; 17 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 18 | import org.springframework.core.io.ClassPathResource; 19 | import org.springframework.core.io.Resource; 20 | import t5750.poi.domain.Book; 21 | import t5750.poi.domain.Student; 22 | 23 | /** 24 | * 利用开源组件POI3.0.2动态导出EXCEL文档 25 | * 26 | * @version v1.0 27 | * @param 28 | * 应用泛型,代表任意一个符合javabean风格的类 29 | * 注意这里为了简单起见,boolean型的属性xxx的get器方式为getXxx(),而不是isXxx() 30 | * byte[]表jpg格式的图片数据 31 | */ 32 | public class ExcelExportUtil { 33 | public void exportExcel(Collection dataset, OutputStream out) { 34 | exportExcel(Globals.SHEETNAME, null, dataset, out, "yyyy-MM-dd"); 35 | } 36 | 37 | public void exportExcel(String[] headers, Collection dataset, 38 | OutputStream out) { 39 | exportExcel(Globals.SHEETNAME, headers, dataset, out, "yyyy-MM-dd"); 40 | } 41 | 42 | public void exportExcel(String[] headers, Collection dataset, 43 | OutputStream out, String pattern) { 44 | exportExcel(Globals.SHEETNAME, headers, dataset, out, pattern); 45 | } 46 | 47 | /** 48 | * 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上 49 | * 50 | * @param title 51 | * 表格标题名 52 | * @param headers 53 | * 表格属性列名数组 54 | * @param dataset 55 | * 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的 56 | * javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据) 57 | * @param out 58 | * 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中 59 | * @param pattern 60 | * 如果有时间数据,设定输出格式。默认为"yyy-MM-dd" 61 | */ 62 | @SuppressWarnings("unchecked") 63 | public void exportExcel(String title, String[] headers, 64 | Collection dataset, OutputStream out, String pattern) { 65 | // 声明一个工作薄 66 | HSSFWorkbook workbook = new HSSFWorkbook(); 67 | // 生成一个表格 68 | HSSFSheet sheet = workbook.createSheet(title); 69 | // 设置表格默认列宽度为15个字节 70 | sheet.setDefaultColumnWidth((short) 15); 71 | // 生成一个样式 72 | HSSFCellStyle style = workbook.createCellStyle(); 73 | // 设置这些样式 74 | style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.SKY_BLUE.getIndex()); 75 | style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 76 | style.setBorderBottom(BorderStyle.THIN); 77 | style.setBorderLeft(BorderStyle.THIN); 78 | style.setBorderRight(BorderStyle.THIN); 79 | style.setBorderTop(BorderStyle.THIN); 80 | style.setAlignment(HorizontalAlignment.CENTER); 81 | // 生成一个字体 82 | HSSFFont font = workbook.createFont(); 83 | font.setColor(HSSFColor.HSSFColorPredefined.VIOLET.getIndex()); 84 | font.setFontHeightInPoints((short) 12); 85 | font.setBold(true); 86 | // 把字体应用到当前的样式 87 | style.setFont(font); 88 | // 生成并设置另一个样式 89 | HSSFCellStyle style2 = workbook.createCellStyle(); 90 | style2.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_YELLOW.getIndex()); 91 | style2.setFillPattern(FillPatternType.SOLID_FOREGROUND); 92 | style2.setBorderBottom(BorderStyle.THIN); 93 | style2.setBorderLeft(BorderStyle.THIN); 94 | style2.setBorderRight(BorderStyle.THIN); 95 | style2.setBorderTop(BorderStyle.THIN); 96 | style2.setAlignment(HorizontalAlignment.CENTER); 97 | style2.setVerticalAlignment(VerticalAlignment.CENTER); 98 | // 生成另一个字体 99 | HSSFFont font2 = workbook.createFont(); 100 | font2.setBold(false); 101 | // 把字体应用到当前的样式 102 | style2.setFont(font2); 103 | // 声明一个画图的顶级管理器 104 | HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); 105 | // 定义注释的大小和位置,详见文档 106 | HSSFComment comment = patriarch.createComment( 107 | new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5)); 108 | // 设置注释内容 109 | comment.setString(new HSSFRichTextString("可以在POI中添加注释!")); 110 | // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容. 111 | comment.setAuthor("leno"); 112 | // 产生表格标题行 113 | HSSFRow row = sheet.createRow(0); 114 | for (short i = 0; i < headers.length; i++) { 115 | HSSFCell cell = row.createCell(i); 116 | cell.setCellStyle(style); 117 | HSSFRichTextString text = new HSSFRichTextString(headers[i]); 118 | cell.setCellValue(text); 119 | } 120 | // 遍历集合数据,产生数据行 121 | Iterator it = dataset.iterator(); 122 | int index = 0; 123 | while (it.hasNext()) { 124 | index++; 125 | row = sheet.createRow(index); 126 | T t = (T) it.next(); 127 | // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值 128 | Field[] fields = t.getClass().getDeclaredFields(); 129 | for (short i = 0; i < fields.length; i++) { 130 | HSSFCell cell = row.createCell(i); 131 | cell.setCellStyle(style2); 132 | Field field = fields[i]; 133 | String fieldName = field.getName(); 134 | String getMethodName = "get" 135 | + fieldName.substring(0, 1).toUpperCase() 136 | + fieldName.substring(1); 137 | try { 138 | Class tCls = t.getClass(); 139 | Method getMethod = tCls.getMethod(getMethodName, 140 | new Class[] {}); 141 | Object value = getMethod.invoke(t, new Object[] {}); 142 | // 判断值的类型后进行强制类型转换 143 | String textValue = null; 144 | // if (value instanceof Integer) { 145 | // int intValue = (Integer) value; 146 | // cell.setCellValue(intValue); 147 | // } else if (value instanceof Float) { 148 | // float fValue = (Float) value; 149 | // textValue = new HSSFRichTextString( 150 | // String.valueOf(fValue)); 151 | // cell.setCellValue(textValue); 152 | // } else if (value instanceof Double) { 153 | // double dValue = (Double) value; 154 | // textValue = new HSSFRichTextString( 155 | // String.valueOf(dValue)); 156 | // cell.setCellValue(textValue); 157 | // } else if (value instanceof Long) { 158 | // long longValue = (Long) value; 159 | // cell.setCellValue(longValue); 160 | // } 161 | if (null == value) { 162 | value = ""; 163 | } 164 | if (value instanceof Boolean) { 165 | boolean bValue = (Boolean) value; 166 | textValue = "男"; 167 | if (!bValue) { 168 | textValue = "女"; 169 | } 170 | } else if (value instanceof Date) { 171 | Date date = (Date) value; 172 | SimpleDateFormat sdf = new SimpleDateFormat(pattern); 173 | textValue = sdf.format(date); 174 | } else if (value instanceof byte[]) { 175 | // 有图片时,设置行高为60px; 176 | row.setHeightInPoints(60); 177 | // 设置图片所在列宽度为80px,注意这里单位的一个换算 178 | sheet.setColumnWidth(i, (short) (35.7 * 80)); 179 | // sheet.autoSizeColumn(i); 180 | byte[] bsValue = (byte[]) value; 181 | HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 182 | 1023, 255, (short) 6, index, (short) 6, index); 183 | anchor.setAnchorType( 184 | ClientAnchor.AnchorType.MOVE_DONT_RESIZE); 185 | patriarch.createPicture(anchor, workbook.addPicture( 186 | bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG)); 187 | } else { 188 | // 其它数据类型都当作字符串简单处理 189 | textValue = value.toString(); 190 | } 191 | // 如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成 192 | if (textValue != null) { 193 | Pattern p = Pattern.compile("^//d+(//.//d+)?$"); 194 | Matcher matcher = p.matcher(textValue); 195 | if (matcher.matches()) { 196 | // 是数字当作double处理 197 | cell.setCellValue(Double.parseDouble(textValue)); 198 | } else { 199 | HSSFRichTextString richString = new HSSFRichTextString( 200 | textValue); 201 | HSSFFont font3 = workbook.createFont(); 202 | font3.setColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex()); 203 | richString.applyFont(font3); 204 | cell.setCellValue(richString); 205 | } 206 | } 207 | } catch (SecurityException e) { 208 | e.printStackTrace(); 209 | } catch (NoSuchMethodException e) { 210 | e.printStackTrace(); 211 | } catch (IllegalArgumentException e) { 212 | e.printStackTrace(); 213 | } catch (IllegalAccessException e) { 214 | e.printStackTrace(); 215 | } catch (InvocationTargetException e) { 216 | e.printStackTrace(); 217 | } finally { 218 | // 清理资源 219 | } 220 | } 221 | } 222 | try { 223 | workbook.write(out); 224 | } catch (IOException e) { 225 | e.printStackTrace(); 226 | } 227 | } 228 | 229 | public static void export2003(String imagesPath, String docsPath) { 230 | // 测试学生 231 | ExcelExportUtil ex = new ExcelExportUtil(); 232 | String[] headers = { "学号", "姓名", "年龄", "性别", "出生日期" }; 233 | List dataset = new ArrayList(); 234 | dataset.add(new Student(10000001L, "张三", 20, true, new Date())); 235 | dataset.add(new Student(20000002L, "李四", 24, false, new Date())); 236 | dataset.add(new Student(30000003L, "王五", 22, true, new Date())); 237 | // 测试图书 238 | ExcelExportUtil exBook = new ExcelExportUtil(); 239 | String[] headersBook = { "图书编号", "图书名称", "图书作者", "图书价格", "图书ISBN", 240 | "图书出版社", "封面图片" }; 241 | List datasetBook = new ArrayList(); 242 | try { 243 | Resource resource = new ClassPathResource(imagesPath); 244 | InputStream is = resource.getInputStream(); 245 | BufferedInputStream bis = new BufferedInputStream(is); 246 | byte[] buf = new byte[bis.available()]; 247 | while ((bis.read(buf)) != -1) { 248 | // 249 | } 250 | datasetBook.add(new Book(1, "jsp", "leno", 300.33f, "1234567", 251 | "清华出版社", buf)); 252 | datasetBook.add(new Book(2, "java编程思想", "brucl", 300.33f, "1234567", 253 | "阳光出版社", buf)); 254 | datasetBook.add(new Book(3, "DOM艺术", "lenotang", 300.33f, "1234567", 255 | "清华出版社", buf)); 256 | datasetBook.add(new Book(4, "c++经典", "leno", 400.33f, "1234567", 257 | "清华出版社", buf)); 258 | datasetBook.add(new Book(5, "c#入门", "leno", 300.33f, "1234567", 259 | "汤春秀出版社", buf)); 260 | OutputStream out = new FileOutputStream( 261 | docsPath + File.separator + Globals.EXPORT_STUDENT); 262 | OutputStream outBook = new FileOutputStream( 263 | docsPath + File.separator + Globals.EXPORT_BOOK); 264 | ex.exportExcel(headers, dataset, out); 265 | exBook.exportExcel(headersBook, datasetBook, outBook); 266 | out.close(); 267 | outBook.close(); 268 | // JOptionPane.showMessageDialog(null, "导出成功!"); 269 | } catch (FileNotFoundException e) { 270 | e.printStackTrace(); 271 | } catch (IOException e) { 272 | e.printStackTrace(); 273 | } 274 | } 275 | 276 | public static void export2007(String filePath) { 277 | try { 278 | // 输出流 279 | OutputStream os = new FileOutputStream(filePath); 280 | // 工作区 281 | XSSFWorkbook wb = new XSSFWorkbook(); 282 | XSSFSheet sheet = wb.createSheet(Globals.SHEETNAME); 283 | for (int i = 0; i < 1000; i++) { 284 | // 创建第一个sheet 285 | // 生成第一行 286 | XSSFRow row = sheet.createRow(i); 287 | // 给这一行的第一列赋值 288 | row.createCell(0).setCellValue("column" + i); 289 | // 给这一行的第一列赋值 290 | row.createCell(1).setCellValue("column" + i); 291 | // System.out.println(i); 292 | } 293 | // 写文件 294 | wb.write(os); 295 | // 关闭输出流 296 | os.close(); 297 | } catch (Exception e) { 298 | e.printStackTrace(); 299 | } 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/ExcelReplaceUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | import java.io.InputStream; 7 | import java.util.List; 8 | 9 | import org.apache.poi.hssf.usermodel.HSSFCell; 10 | import org.apache.poi.hssf.usermodel.HSSFRow; 11 | import org.apache.poi.hssf.usermodel.HSSFSheet; 12 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 13 | import org.apache.poi.poifs.filesystem.POIFSFileSystem; 14 | import org.apache.poi.ss.usermodel.CellType; 15 | import t5750.poi.command.ExcelReplaceDataVO; 16 | 17 | public class ExcelReplaceUtil { 18 | /** 19 | * 替换Excel模板文件内容 20 | * 21 | * @param datas 22 | * 文档数据 23 | * @param is 24 | * Excel模板文件路径 25 | * @param targetFilePath 26 | * Excel生成文件路径 27 | */ 28 | public static boolean replaceModel(List datas, 29 | InputStream is, String targetFilePath) { 30 | boolean bool = true; 31 | try { 32 | POIFSFileSystem fs = new POIFSFileSystem(is); 33 | HSSFWorkbook wb = new HSSFWorkbook(fs); 34 | HSSFSheet sheet = wb.getSheetAt(0); 35 | for (ExcelReplaceDataVO data : datas) { 36 | // 获取单元格内容 37 | HSSFRow row = sheet.getRow(data.getRow()); 38 | HSSFCell cell = row.getCell((short) data.getColumn()); 39 | String str = cell.getStringCellValue(); 40 | // 替换单元格内容 41 | str = str.replace(data.getKey(), data.getValue()); 42 | // 写入单元格内容 43 | cell.setCellType(CellType.STRING); 44 | // cell.setEncoding(HSSFCell.ENCODING_UTF_16); 45 | cell.setCellValue(str); 46 | } 47 | // 输出文件 48 | FileOutputStream fileOut = new FileOutputStream(targetFilePath); 49 | wb.write(fileOut); 50 | fileOut.close(); 51 | } catch (Exception e) { 52 | bool = false; 53 | e.printStackTrace(); 54 | } 55 | return bool; 56 | } 57 | 58 | public static boolean replaceModel(List datas, 59 | String sourceFilePath, String targetFilePath) 60 | throws FileNotFoundException { 61 | return replaceModel(datas, new FileInputStream(sourceFilePath), 62 | targetFilePath); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/ExcelTemplateUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.*; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 10 | import org.apache.poi.ss.usermodel.*; 11 | 12 | /** 13 | * 用于处理Excel写操作 14 | */ 15 | public class ExcelTemplateUtil { 16 | // 开始位置 17 | public final static String TEMPLATE_NAME = "datastart"; 18 | // 样式,用于要标志自定义的样式的列. 19 | public final static String STYLE = "style"; 20 | // 默认样式 21 | public final static String DEFALULT_STYLE = "defaultStyle"; 22 | // 序号,确定Excel是否需要样式. 23 | public final static String SERNUMS = "sernums"; 24 | private int initRowIndex; // 初始行 25 | private int initColIndex; // 初始列 26 | private int curRowIndex; // 当前行 27 | private int curColIndex; // 当前列 28 | private int lastRowInex; // 最后一行 29 | private float defaultHeight; // 默认行高 30 | private int serColIndex; // 序号行. 31 | private Workbook workbook = null; 32 | private Sheet sheet = null; 33 | private Row curRow = null; // 当前行 34 | // 样式 35 | private Map styles = null; 36 | // 默认样式 37 | private CellStyle defaultStyle = null; 38 | // 使用单例 39 | private static ExcelTemplateUtil excel = new ExcelTemplateUtil(); 40 | 41 | private ExcelTemplateUtil() { 42 | } 43 | 44 | public static ExcelTemplateUtil getInstance() { 45 | return excel; 46 | } 47 | 48 | /** 49 | * 读取模板(从classpath中) 50 | * 51 | * @param calsspath 52 | * 模板路径 53 | * @return ExcelTemplate 54 | */ 55 | public ExcelTemplateUtil readTemplateClassPath(String calsspath) { 56 | try { 57 | workbook = WorkbookFactory.create( 58 | ExcelTemplateUtil.class.getResourceAsStream(calsspath)); 59 | initTemplate(); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | throw new RuntimeException("读取模板文件不存在!请检查."); 63 | } 64 | return this; 65 | } 66 | 67 | /** 68 | * 读取模板(从指定路径) 69 | * 70 | * @param path 71 | * 模板路径 72 | * @return ExcelTemplate 73 | */ 74 | public ExcelTemplateUtil readTemplatePath(String path) { 75 | try { 76 | workbook = WorkbookFactory.create(new File(path)); 77 | initTemplate(); 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | throw new RuntimeException("读取模板文件不存在!请检查."); 81 | } 82 | return this; 83 | } 84 | 85 | public ExcelTemplateUtil readTemplatePath(InputStream is) { 86 | try { 87 | workbook = WorkbookFactory.create(is); 88 | initTemplate(); 89 | } catch (IOException e) { 90 | e.printStackTrace(); 91 | throw new RuntimeException("读取模板文件不存在!请检查."); 92 | } 93 | return this; 94 | } 95 | 96 | /** 97 | * 创建新的一行 98 | */ 99 | public void creatNewRow() { 100 | // curRowIndex != initRowIndxe : 当前行本身是存在的,所以下移多余. 101 | if (lastRowInex > curRowIndex && curRowIndex != initRowIndex) { 102 | sheet.shiftRows(curRowIndex, lastRowInex, 1, true, true); // 有的模板最后可能是日期或者姓名之类的非数据.所以要移动行. 103 | lastRowInex++; 104 | } 105 | curRow = sheet.createRow(curRowIndex); 106 | curRow.setHeightInPoints(defaultHeight); 107 | curRowIndex++; 108 | curColIndex = initColIndex; 109 | } 110 | 111 | public void createNewCol(String value) { 112 | Cell cell = curRow.createCell(curColIndex); 113 | setStyle(cell); 114 | cell.setCellValue(value); 115 | curColIndex++; 116 | } 117 | 118 | public void createNewCol(double value) { 119 | Cell cell = curRow.createCell(curColIndex); 120 | setStyle(cell); 121 | cell.setCellValue(value); 122 | curColIndex++; 123 | } 124 | 125 | public void createNewCol(boolean value) { 126 | Cell cell = curRow.createCell(curColIndex); 127 | setStyle(cell); 128 | cell.setCellValue(value); 129 | curColIndex++; 130 | } 131 | 132 | public void createNewCol(Date value) { 133 | Cell cell = curRow.createCell(curColIndex); 134 | setStyle(cell); 135 | cell.setCellValue(value); 136 | curColIndex++; 137 | } 138 | 139 | public void createNewCol(Calendar value) { 140 | Cell cell = curRow.createCell(curColIndex); 141 | setStyle(cell); 142 | cell.setCellValue(value); 143 | curColIndex++; 144 | } 145 | 146 | public void createNewCol(RichTextString value) { 147 | Cell cell = curRow.createCell(curColIndex); 148 | setStyle(cell); 149 | cell.setCellValue(value); 150 | curColIndex++; 151 | } 152 | 153 | /** 154 | * 根据#xxx替换模板中的其它样式. 155 | * 156 | * @param datas 157 | * 要替换的数据 158 | */ 159 | public void replaceFind(Map datas) { 160 | if (datas == null) 161 | return; 162 | for (Row row : sheet) { 163 | for (Cell cell : row) { 164 | if (cell.getCellType() != CellType.STRING) 165 | continue; 166 | String value = cell.getStringCellValue().trim(); 167 | if (value.startsWith("#")) { 168 | if (datas.containsKey(value.substring(1))) { 169 | cell.setCellValue(datas.get(value.substring(1))); 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | /** 177 | * 插入序号 178 | */ 179 | public void insertSer() { 180 | int index = 1; 181 | Row row = null; 182 | Cell cell = null; 183 | for (int i = initRowIndex; i < curRowIndex; i++) { 184 | row = sheet.getRow(i); 185 | cell = row.createCell(serColIndex); 186 | setStyle(cell); 187 | cell.setCellValue(index++); 188 | } 189 | } 190 | 191 | /** 192 | * 输出文件,根据路径 193 | * 194 | * @param path 195 | * 路径 196 | */ 197 | public void writeToFile(String path) { 198 | FileOutputStream fos = null; 199 | try { 200 | fos = new FileOutputStream(path); 201 | workbook.write(fos); 202 | } catch (FileNotFoundException e) { 203 | e.printStackTrace(); 204 | throw new RuntimeException("找不到文件!请检查."); 205 | } catch (IOException e) { 206 | e.printStackTrace(); 207 | throw new RuntimeException("文件输出异常!请检查."); 208 | } finally { 209 | try { 210 | if (fos != null) { 211 | fos.close(); 212 | fos = null; 213 | } 214 | } catch (IOException e) { 215 | e.printStackTrace(); 216 | } 217 | } 218 | } 219 | 220 | /** 221 | * 输出文件,根据流输出 222 | * 223 | * @param stream 224 | * OutputStream 225 | */ 226 | public void writeToStream(OutputStream stream) { 227 | try { 228 | workbook.write(stream); 229 | } catch (IOException e) { 230 | e.printStackTrace(); 231 | throw new RuntimeException("文件输出异常!请检查."); 232 | } finally { 233 | try { 234 | if (stream != null) { 235 | stream.close(); 236 | stream = null; 237 | } 238 | } catch (IOException e) { 239 | e.printStackTrace(); 240 | } 241 | } 242 | } 243 | 244 | /** 245 | * 初始化模板 246 | */ 247 | private void initTemplate() { 248 | sheet = workbook.getSheetAt(0); 249 | styles = new HashMap(); 250 | initConfigData(); 251 | lastRowInex = sheet.getLastRowNum(); 252 | } 253 | 254 | /** 255 | * defaultStyles:获得默认样式(如果默认样式没有则使用开始样式) styles:获取自定义样式 256 | * 257 | */ 258 | private void initConfigData() { 259 | for (Row row : sheet) { 260 | for (Cell cell : row) { 261 | if (cell.getCellType() != CellType.STRING) 262 | continue; 263 | String value = cell.getStringCellValue().trim(); 264 | // 获取开始位置,初始化数据 265 | if (TEMPLATE_NAME.equals(value)) { 266 | initRowIndex = cell.getRowIndex(); 267 | initColIndex = cell.getColumnIndex(); 268 | curRowIndex = initRowIndex; 269 | curColIndex = initColIndex; 270 | defaultHeight = row.getHeightInPoints(); 271 | if (defaultStyle == null) 272 | defaultStyle = cell.getCellStyle(); 273 | } 274 | // 获取defaultStyles,无论如何,当有设置defaultStyles都设置为defaultStyles 275 | if (DEFALULT_STYLE.equals(value)) 276 | defaultStyle = cell.getCellStyle(); 277 | // 获取自定义样式的列 278 | if (STYLE.equals(value)) { 279 | styles.put(cell.getColumnIndex(), cell.getCellStyle()); 280 | } 281 | // 获取样式所在的列 282 | if (SERNUMS.equals(value)) 283 | serColIndex = cell.getColumnIndex(); 284 | } 285 | } 286 | } 287 | 288 | /** 289 | * 设置样式 290 | * 291 | * @param cell 292 | * Cell 293 | */ 294 | private void setStyle(Cell cell) { 295 | // 当前列存在自定义样式时使用自定义样式,否则使用默认样式. 296 | if (styles.containsKey(curColIndex)) { 297 | cell.setCellStyle(styles.get(curColIndex)); 298 | } else { 299 | cell.setCellStyle(defaultStyle); 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/Globals.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.File; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | public class Globals { 8 | public static final String DOC = "doc"; 9 | public static final String IMG = "img"; 10 | public static final String DOC_PATH = ClassLoaderUtil.getClassPath() 11 | + File.separator + DOC; 12 | public static final String IMG_PATH = ClassLoaderUtil.getClassPath() 13 | + File.separator + IMG; 14 | public static final String SUFFIX_XLS = ".xls"; 15 | public static final String SUFFIX_XLSX = ".xlsx"; 16 | public static final String SUFFIX_PNG = ".png"; 17 | public static final String EXPORT_STUDENT = "student" 18 | + System.currentTimeMillis() + SUFFIX_XLS; 19 | public static final String EXPORT_BOOK = "book" 20 | + System.currentTimeMillis() + SUFFIX_XLS; 21 | public static final String EXPORT_2007 = "export2007中文_" 22 | + System.currentTimeMillis() + SUFFIX_XLSX; 23 | public static final String EXPORT_PRODUCT = "product" 24 | + System.currentTimeMillis() + SUFFIX_XLS; 25 | public static final String SHEETNAME = "测试POI导出EXCEL文档"; 26 | 27 | public static String getBasePath(HttpServletRequest request) { 28 | String path = request.getContextPath(); 29 | String basePath = request.getScheme() + "://" + request.getServerName() 30 | + ":" + request.getServerPort() + path + "/"; 31 | return basePath; 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/HuExcelUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | import java.io.IOException; 4 | import java.net.URLEncoder; 5 | import java.util.List; 6 | 7 | import javax.servlet.ServletOutputStream; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import cn.hutool.core.date.DateUtil; 11 | import cn.hutool.core.io.IoUtil; 12 | import cn.hutool.poi.excel.ExcelUtil; 13 | import cn.hutool.poi.excel.ExcelWriter; 14 | import t5750.poi.domain.SheetDTO; 15 | 16 | /** 17 | * Hutool导出Excel,导多个Sheet页 19 | */ 20 | public class HuExcelUtil { 21 | /** 22 | * 导出多个 Sheet 页 23 | * 24 | * @param response 25 | * @param sheetList 26 | * 页数据 27 | * @param fileName 28 | * 文件名 29 | */ 30 | public static void exportExcel(HttpServletResponse response, 31 | List sheetList, String fileName) { 32 | ExcelWriter bigWriter = ExcelUtil.getBigWriter(); 33 | // 重命名第一个Sheet的名称,不然会默认多出一个Sheet1的页 34 | bigWriter.renameSheet(0, sheetList.get(0).getSheetName()); 35 | for (SheetDTO sheet : sheetList) { 36 | // 指定要写出的 Sheet 页 37 | bigWriter.setSheet(sheet.getSheetName()); 38 | List columnWidth = sheet.getColumnWidth(); 39 | if (columnWidth == null 40 | || columnWidth.size() != sheet.getFieldAndAlias().size()) { 41 | // 设置默认宽度 42 | for (int i = 0; i < sheet.getFieldAndAlias().size(); i++) { 43 | bigWriter.setColumnWidth(i, 25); 44 | } 45 | } else { 46 | // 设置自定义宽度 47 | for (int i = 0; i < columnWidth.size(); i++) { 48 | bigWriter.setColumnWidth(i, columnWidth.get(i)); 49 | } 50 | } 51 | // 设置字段和别名 52 | bigWriter.setHeaderAlias(sheet.getFieldAndAlias()); 53 | // 设置只导出有别名的字段 54 | bigWriter.setOnlyAlias(true); 55 | // 设置默认行高 56 | bigWriter.setDefaultRowHeight(18); 57 | // 设置冻结行 58 | bigWriter.setFreezePane(1); 59 | // 一次性写出内容,使用默认样式,强制输出标题 60 | bigWriter.write(sheet.getCollection(), true); 61 | // 设置所有列为自动宽度,不考虑合并单元格 62 | // bigWriter.autoSizeColumnAll(); 63 | } 64 | ServletOutputStream out = null; 65 | try { 66 | // response为HttpServletResponse对象 67 | response.setContentType("application/vnd.ms-excel;charset=utf-8"); 68 | response.setHeader("Content-Disposition", 69 | "attachment;filename=" + URLEncoder.encode( 70 | fileName + DateUtil.today() + ".xlsx", "UTF-8")); 71 | out = response.getOutputStream(); 72 | bigWriter.flush(out, true); 73 | } catch (IOException e) { 74 | e.printStackTrace(); 75 | } finally { 76 | // 关闭writer,释放内存 77 | bigWriter.close(); 78 | } 79 | // 此处记得关闭输出Servlet流 80 | IoUtil.close(out); 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/java/t5750/poi/util/OSinfo.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | public class OSinfo { 4 | private static String OS = System.getProperty("os.name").toLowerCase(); 5 | private static OSinfo _instance = new OSinfo(); 6 | private EPlatform platform; 7 | 8 | private OSinfo() { 9 | } 10 | 11 | public static boolean isLinux() { 12 | return OS.indexOf("linux") >= 0; 13 | } 14 | 15 | public static boolean isMacOS() { 16 | return OS.indexOf("mac") >= 0 && OS.indexOf("os") > 0 17 | && OS.indexOf("x") < 0; 18 | } 19 | 20 | public static boolean isMacOSX() { 21 | return OS.indexOf("mac") >= 0 && OS.indexOf("os") > 0 22 | && OS.indexOf("x") > 0; 23 | } 24 | 25 | public static boolean isWindows() { 26 | return OS.indexOf("windows") >= 0; 27 | } 28 | 29 | public static boolean isOS2() { 30 | return OS.indexOf("os/2") >= 0; 31 | } 32 | 33 | public static boolean isSolaris() { 34 | return OS.indexOf("solaris") >= 0; 35 | } 36 | 37 | public static boolean isSunOS() { 38 | return OS.indexOf("sunos") >= 0; 39 | } 40 | 41 | public static boolean isMPEiX() { 42 | return OS.indexOf("mpe/ix") >= 0; 43 | } 44 | 45 | public static boolean isHPUX() { 46 | return OS.indexOf("hp-ux") >= 0; 47 | } 48 | 49 | public static boolean isAix() { 50 | return OS.indexOf("aix") >= 0; 51 | } 52 | 53 | public static boolean isOS390() { 54 | return OS.indexOf("os/390") >= 0; 55 | } 56 | 57 | public static boolean isFreeBSD() { 58 | return OS.indexOf("freebsd") >= 0; 59 | } 60 | 61 | public static boolean isIrix() { 62 | return OS.indexOf("irix") >= 0; 63 | } 64 | 65 | public static boolean isDigitalUnix() { 66 | return OS.indexOf("digital") >= 0 && OS.indexOf("unix") > 0; 67 | } 68 | 69 | public static boolean isNetWare() { 70 | return OS.indexOf("netware") >= 0; 71 | } 72 | 73 | public static boolean isOSF1() { 74 | return OS.indexOf("osf1") >= 0; 75 | } 76 | 77 | public static boolean isOpenVMS() { 78 | return OS.indexOf("openvms") >= 0; 79 | } 80 | 81 | /** 82 | * 获取操作系统名字 83 | * 84 | * @return 操作系统名 85 | */ 86 | public static EPlatform getOSname() { 87 | if (isAix()) { 88 | _instance.platform = EPlatform.AIX; 89 | } else if (isDigitalUnix()) { 90 | _instance.platform = EPlatform.Digital_Unix; 91 | } else if (isFreeBSD()) { 92 | _instance.platform = EPlatform.FreeBSD; 93 | } else if (isHPUX()) { 94 | _instance.platform = EPlatform.HP_UX; 95 | } else if (isIrix()) { 96 | _instance.platform = EPlatform.Irix; 97 | } else if (isLinux()) { 98 | _instance.platform = EPlatform.Linux; 99 | } else if (isMacOS()) { 100 | _instance.platform = EPlatform.Mac_OS; 101 | } else if (isMacOSX()) { 102 | _instance.platform = EPlatform.Mac_OS_X; 103 | } else if (isMPEiX()) { 104 | _instance.platform = EPlatform.MPEiX; 105 | } else if (isNetWare()) { 106 | _instance.platform = EPlatform.NetWare_411; 107 | } else if (isOpenVMS()) { 108 | _instance.platform = EPlatform.OpenVMS; 109 | } else if (isOS2()) { 110 | _instance.platform = EPlatform.OS2; 111 | } else if (isOS390()) { 112 | _instance.platform = EPlatform.OS390; 113 | } else if (isOSF1()) { 114 | _instance.platform = EPlatform.OSF1; 115 | } else if (isSolaris()) { 116 | _instance.platform = EPlatform.Solaris; 117 | } else if (isSunOS()) { 118 | _instance.platform = EPlatform.SunOS; 119 | } else if (isWindows()) { 120 | _instance.platform = EPlatform.Windows; 121 | } else { 122 | _instance.platform = EPlatform.Others; 123 | } 124 | return _instance.platform; 125 | } 126 | 127 | /** 128 | * @param args 129 | */ 130 | public static void main(String[] args) { 131 | System.out.println(OSinfo.getOSname()); 132 | } 133 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=poi 2 | server.servlet.context-path=/${spring.application.name} 3 | spring.jpa.show-sql=true 4 | spring.jpa.hibernate.ddl-auto=update 5 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.DerbyTenSevenDialect 6 | #spring.datasource.url=jdbc:derby:D:/code/derbypoi;create=true -------------------------------------------------------------------------------- /src/main/resources/doc/productImport.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/T5750/poi-repositories/6589bcd16cf7587a3eb7ec88ecf59667be3d75b8/src/main/resources/doc/productImport.xls -------------------------------------------------------------------------------- /src/main/resources/doc/replaceTemplate.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/T5750/poi-repositories/6589bcd16cf7587a3eb7ec88ecf59667be3d75b8/src/main/resources/doc/replaceTemplate.xls -------------------------------------------------------------------------------- /src/main/resources/doc/template.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/T5750/poi-repositories/6589bcd16cf7587a3eb7ec88ecf59667be3d75b8/src/main/resources/doc/template.xls -------------------------------------------------------------------------------- /src/main/resources/doc/testRead.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/T5750/poi-repositories/6589bcd16cf7587a3eb7ec88ecf59667be3d75b8/src/main/resources/doc/testRead.xls -------------------------------------------------------------------------------- /src/main/resources/img/tomcat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/T5750/poi-repositories/6589bcd16cf7587a3eb7ec88ecf59667be3d75b8/src/main/resources/img/tomcat.png -------------------------------------------------------------------------------- /src/main/resources/templates/product/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | POI Repositories - List Products 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 |
21 | 40 |
41 |
42 |
43 |

Product List

44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
IdDescriptionPriceImage URLListEditDelete
ViewEditDelete
65 |
66 | 71 |

Older

72 | 80 |
81 |
82 |
83 |
84 | © 2014-2024 T5750 85 |
86 |
87 | 88 | -------------------------------------------------------------------------------- /src/main/resources/templates/product/productform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | POI Repositories - Product Form 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 |
21 | 40 |
41 |
42 |
43 |

Product Details

44 |
45 |
46 | 47 | 48 | 49 | 50 |
51 | 52 |
53 | 54 | 55 |
    56 |
  • 57 |
58 |
59 |
60 |
61 |
62 | 63 |
64 | 65 | 66 |
    67 |
  • 68 |
69 |
70 |
71 |
72 |
73 | 74 |
75 | 76 | 77 |
    78 |
  • 79 |
80 |
81 |
82 |
83 |
84 | Home 85 | 86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | © 2014-2024 T5750 94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /src/main/resources/templates/product/show.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | POI Repositories - Show Product 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 |
21 | 40 |
41 |
42 |
43 |

Show Product

44 |
45 |
46 |
47 | 48 |
49 |

Product Id

50 |
51 |
52 |
53 | 54 |
55 |

Description

56 |
57 |
58 |
59 | 60 |
61 |

Price

62 |
63 |
64 |
65 | 66 |
67 |

Image

68 |
69 |
70 |
71 |
72 |
73 | Home 74 |
75 |
76 |
77 |
78 |
79 | © 2014-2024 T5750 80 |
81 |
82 | 83 | -------------------------------------------------------------------------------- /src/test/java/org/apache/poi/ss/examples/CalendarDemo.java: -------------------------------------------------------------------------------- 1 | package org.apache.poi.ss.examples; 2 | 3 | import org.apache.poi.xssf.usermodel.*; 4 | import org.apache.poi.ss.util.CellRangeAddress; 5 | import org.apache.poi.ss.usermodel.*; 6 | import org.apache.poi.ss.usermodel.Font; 7 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 8 | 9 | import java.io.FileOutputStream; 10 | import java.util.Calendar; 11 | import java.util.Map; 12 | import java.util.HashMap; 13 | 14 | /** 15 | * A monthly calendar created using Apache POI. Each month is on a separate sheet. 16 | *
 17 |  * Usage:
 18 |  * CalendarDemo -xls|xlsx 
 19 |  * 
20 | * 21 | * @author Yegor Kozlov 22 | */ 23 | public class CalendarDemo { 24 | 25 | private static final String[] days = { 26 | "Sunday", "Monday", "Tuesday", 27 | "Wednesday", "Thursday", "Friday", "Saturday"}; 28 | 29 | private static final String[] months = { 30 | "January", "February", "March","April", "May", "June","July", "August", 31 | "September","October", "November", "December"}; 32 | 33 | public static void main(String[] args) throws Exception { 34 | 35 | Calendar calendar = Calendar.getInstance(); 36 | boolean xlsx = true; 37 | for (String arg : args) { 38 | if (arg.charAt(0) == '-') { 39 | xlsx = arg.equals("-xlsx"); 40 | } else { 41 | calendar.set(Calendar.YEAR, Integer.parseInt(arg)); 42 | } 43 | } 44 | int year = calendar.get(Calendar.YEAR); 45 | Workbook wb = xlsx ? new XSSFWorkbook() : new HSSFWorkbook(); 46 | // try (Workbook wb = xlsx ? new XSSFWorkbook() : new HSSFWorkbook()) { 47 | try { 48 | 49 | Map styles = createStyles(wb); 50 | 51 | for (int month = 0; month < 12; month++) { 52 | calendar.set(Calendar.MONTH, month); 53 | calendar.set(Calendar.DAY_OF_MONTH, 1); 54 | //create a sheet for each month 55 | Sheet sheet = wb.createSheet(months[month]); 56 | 57 | //turn off gridlines 58 | sheet.setDisplayGridlines(false); 59 | sheet.setPrintGridlines(false); 60 | sheet.setFitToPage(true); 61 | sheet.setHorizontallyCenter(true); 62 | PrintSetup printSetup = sheet.getPrintSetup(); 63 | printSetup.setLandscape(true); 64 | 65 | //the following three statements are required only for HSSF 66 | sheet.setAutobreaks(true); 67 | printSetup.setFitHeight((short) 1); 68 | printSetup.setFitWidth((short) 1); 69 | 70 | //the header row: centered text in 48pt font 71 | Row headerRow = sheet.createRow(0); 72 | headerRow.setHeightInPoints(80); 73 | Cell titleCell = headerRow.createCell(0); 74 | titleCell.setCellValue(months[month] + " " + year); 75 | titleCell.setCellStyle(styles.get("title")); 76 | sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$N$1")); 77 | 78 | //header with month titles 79 | Row monthRow = sheet.createRow(1); 80 | for (int i = 0; i < days.length; i++) { 81 | //set column widths, the width is measured in units of 1/256th of a character width 82 | sheet.setColumnWidth(i * 2, 5 * 256); //the column is 5 characters wide 83 | sheet.setColumnWidth(i * 2 + 1, 13 * 256); //the column is 13 characters wide 84 | sheet.addMergedRegion(new CellRangeAddress(1, 1, i * 2, i * 2 + 1)); 85 | Cell monthCell = monthRow.createCell(i * 2); 86 | monthCell.setCellValue(days[i]); 87 | monthCell.setCellStyle(styles.get("month")); 88 | } 89 | 90 | int cnt = 1, day = 1; 91 | int rownum = 2; 92 | for (int j = 0; j < 6; j++) { 93 | Row row = sheet.createRow(rownum++); 94 | row.setHeightInPoints(100); 95 | for (int i = 0; i < days.length; i++) { 96 | Cell dayCell_1 = row.createCell(i * 2); 97 | Cell dayCell_2 = row.createCell(i * 2 + 1); 98 | 99 | int day_of_week = calendar.get(Calendar.DAY_OF_WEEK); 100 | if (cnt >= day_of_week && calendar.get(Calendar.MONTH) == month) { 101 | dayCell_1.setCellValue(day); 102 | calendar.set(Calendar.DAY_OF_MONTH, ++day); 103 | 104 | if (i == 0 || i == days.length - 1) { 105 | dayCell_1.setCellStyle(styles.get("weekend_left")); 106 | dayCell_2.setCellStyle(styles.get("weekend_right")); 107 | } else { 108 | dayCell_1.setCellStyle(styles.get("workday_left")); 109 | dayCell_2.setCellStyle(styles.get("workday_right")); 110 | } 111 | } else { 112 | dayCell_1.setCellStyle(styles.get("grey_left")); 113 | dayCell_2.setCellStyle(styles.get("grey_right")); 114 | } 115 | cnt++; 116 | } 117 | if (calendar.get(Calendar.MONTH) > month) break; 118 | } 119 | } 120 | 121 | // Write the output to a file 122 | String file = "calendar.xls"; 123 | if (wb instanceof XSSFWorkbook) file += "x"; 124 | 125 | try (FileOutputStream out = new FileOutputStream(file)) { 126 | wb.write(out); 127 | } 128 | }catch (Exception e){ 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | /** 134 | * cell styles used for formatting calendar sheets 135 | */ 136 | private static Map createStyles(Workbook wb){ 137 | Map styles = new HashMap<>(); 138 | 139 | short borderColor = IndexedColors.GREY_50_PERCENT.getIndex(); 140 | 141 | CellStyle style; 142 | Font titleFont = wb.createFont(); 143 | titleFont.setFontHeightInPoints((short)48); 144 | titleFont.setColor(IndexedColors.DARK_BLUE.getIndex()); 145 | style = wb.createCellStyle(); 146 | // style.setAlignment(HorizontalAlignment.CENTER); 147 | // style.setVerticalAlignment(VerticalAlignment.CENTER); 148 | style.setFont(titleFont); 149 | styles.put("title", style); 150 | 151 | Font monthFont = wb.createFont(); 152 | monthFont.setFontHeightInPoints((short)12); 153 | monthFont.setColor(IndexedColors.WHITE.getIndex()); 154 | // monthFont.setBold(true); 155 | style = wb.createCellStyle(); 156 | // style.setAlignment(HorizontalAlignment.CENTER); 157 | // style.setVerticalAlignment(VerticalAlignment.CENTER); 158 | style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex()); 159 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 160 | style.setFont(monthFont); 161 | styles.put("month", style); 162 | 163 | Font dayFont = wb.createFont(); 164 | dayFont.setFontHeightInPoints((short)14); 165 | // dayFont.setBold(true); 166 | style = wb.createCellStyle(); 167 | // style.setAlignment(HorizontalAlignment.LEFT); 168 | // style.setVerticalAlignment(VerticalAlignment.TOP); 169 | style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex()); 170 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 171 | // style.setBorderLeft(BorderStyle.THIN); 172 | style.setLeftBorderColor(borderColor); 173 | // style.setBorderBottom(BorderStyle.THIN); 174 | style.setBottomBorderColor(borderColor); 175 | style.setFont(dayFont); 176 | styles.put("weekend_left", style); 177 | 178 | style = wb.createCellStyle(); 179 | // style.setAlignment(HorizontalAlignment.CENTER); 180 | // style.setVerticalAlignment(VerticalAlignment.TOP); 181 | style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex()); 182 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 183 | // style.setBorderRight(BorderStyle.THIN); 184 | style.setRightBorderColor(borderColor); 185 | // style.setBorderBottom(BorderStyle.THIN); 186 | style.setBottomBorderColor(borderColor); 187 | styles.put("weekend_right", style); 188 | 189 | style = wb.createCellStyle(); 190 | // style.setAlignment(HorizontalAlignment.LEFT); 191 | // style.setVerticalAlignment(VerticalAlignment.TOP); 192 | // style.setBorderLeft(BorderStyle.THIN); 193 | style.setFillForegroundColor(IndexedColors.WHITE.getIndex()); 194 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 195 | style.setLeftBorderColor(borderColor); 196 | // style.setBorderBottom(BorderStyle.THIN); 197 | style.setBottomBorderColor(borderColor); 198 | style.setFont(dayFont); 199 | styles.put("workday_left", style); 200 | 201 | style = wb.createCellStyle(); 202 | // style.setAlignment(HorizontalAlignment.CENTER); 203 | // style.setVerticalAlignment(VerticalAlignment.TOP); 204 | style.setFillForegroundColor(IndexedColors.WHITE.getIndex()); 205 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 206 | // style.setBorderRight(BorderStyle.THIN); 207 | style.setRightBorderColor(borderColor); 208 | // style.setBorderBottom(BorderStyle.THIN); 209 | style.setBottomBorderColor(borderColor); 210 | styles.put("workday_right", style); 211 | 212 | style = wb.createCellStyle(); 213 | // style.setBorderLeft(BorderStyle.THIN); 214 | style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); 215 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 216 | // style.setBorderBottom(BorderStyle.THIN); 217 | style.setBottomBorderColor(borderColor); 218 | styles.put("grey_left", style); 219 | 220 | style = wb.createCellStyle(); 221 | style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); 222 | // style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 223 | // style.setBorderRight(BorderStyle.THIN); 224 | style.setRightBorderColor(borderColor); 225 | // style.setBorderBottom(BorderStyle.THIN); 226 | style.setBottomBorderColor(borderColor); 227 | styles.put("grey_right", style); 228 | 229 | return styles; 230 | } 231 | } -------------------------------------------------------------------------------- /src/test/java/t5750/poi/TestAll.java: -------------------------------------------------------------------------------- 1 | package t5750.poi; 2 | 3 | import org.apache.poi.ss.examples.CalendarDemo; 4 | 5 | import t5750.poi.export.TestExcelFormulaDemo; 6 | import t5750.poi.export.TestExcelStylingDemo; 7 | import t5750.poi.export.TestExportExcel2007; 8 | import t5750.poi.export.TestWriteExcelDemo; 9 | import t5750.poi.read.TestReadExcelDemo; 10 | import t5750.poi.replace.TestExcelReplace; 11 | import t5750.poi.template.TestTemplate; 12 | 13 | public class TestAll { 14 | public static void main(String[] args) throws Exception { 15 | TestExportExcel2007.main(args); 16 | System.out.println(); 17 | TestTemplate.main(args); 18 | System.out.println(); 19 | TestExcelReplace.main(args); 20 | System.out.println(); 21 | TestWriteExcelDemo.main(args); 22 | System.out.println(); 23 | TestReadExcelDemo.main(args); 24 | System.out.println(); 25 | TestExcelFormulaDemo.main(args); 26 | System.out.println(); 27 | TestExcelStylingDemo.main(args); 28 | System.out.println(); 29 | CalendarDemo.main(args); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/TestHutoolPoi.java: -------------------------------------------------------------------------------- 1 | package t5750.poi; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.junit.Test; 7 | 8 | import cn.hutool.core.collection.CollUtil; 9 | import cn.hutool.core.date.DateUtil; 10 | import cn.hutool.core.lang.Console; 11 | import cn.hutool.poi.excel.BigExcelWriter; 12 | import cn.hutool.poi.excel.ExcelReader; 13 | import cn.hutool.poi.excel.ExcelUtil; 14 | import cn.hutool.poi.excel.sax.Excel07SaxReader; 15 | import cn.hutool.poi.excel.sax.handler.RowHandler; 16 | 17 | public class TestHutoolPoi { 18 | public static final String FILE_PATH = "D:/TestHutoolPoi.xlsx"; 19 | 20 | /** 21 | * Excel大数据生成-BigExcelWriter 23 | */ 24 | @Test 25 | public void testBigExcelWriter() { 26 | List row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd", 27 | DateUtil.date(), 3.22676575765); 28 | List row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1", 29 | DateUtil.date(), 250.7676); 30 | List row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2", 31 | DateUtil.date(), 0.111); 32 | List row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3", 33 | DateUtil.date(), 35); 34 | List row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4", 35 | DateUtil.date(), 28.00); 36 | List> rows = CollUtil.newArrayList(row1, row2, row3, row4, 37 | row5); 38 | BigExcelWriter writer = ExcelUtil.getBigWriter(FILE_PATH); 39 | // 一次性写出内容,使用默认样式 40 | writer.write(rows); 41 | // 关闭writer,释放内存 42 | writer.close(); 43 | } 44 | 45 | /** 46 | * Excel读取-ExcelReader 48 | */ 49 | @Test 50 | public void testExcelReader() { 51 | ExcelReader reader = ExcelUtil.getReader(FILE_PATH); 52 | // 1.读取Excel中所有行和列,用二维列表表示 53 | List> readAllList = reader.read(); 54 | System.out.println(readAllList); 55 | List> readAllMap = reader.readAll(); 56 | // 2.读取为Map列表,默认第一行为标题行,数据从第二行开始,一个Map表示一行,Map中的key为标题,value为标题对应的单元格值 57 | System.out.println(readAllMap); 58 | // 3.读取为Bean列表,Bean中的字段名为标题,字段值为标题对应的单元格值 59 | // List all = reader.readAll(Person.class); 60 | } 61 | 62 | /** 63 | * 流方式读取Excel2007-Excel07SaxReader 65 | */ 66 | @Test 67 | public void testExcel07SaxReader() { 68 | ExcelUtil.readBySax(FILE_PATH, "sheet1", createRowHandler()); 69 | // reader方法的第二个参数是sheet的序号,-1表示读取所有sheet,0表示第一个sheet 70 | Excel07SaxReader reader = new Excel07SaxReader(createRowHandler()); 71 | Excel07SaxReader excel07SaxReader = reader.read(FILE_PATH, 0); 72 | } 73 | 74 | private RowHandler createRowHandler() { 75 | return new RowHandler() { 76 | @Override 77 | public void handle(int sheetIndex, long rowIndex, 78 | List rowlist) { 79 | Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowlist); 80 | } 81 | }; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/export/TestExcelFormulaDemo.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.export; 2 | 3 | import java.io.*; 4 | import java.util.Iterator; 5 | 6 | import org.apache.poi.ss.usermodel.Cell; 7 | import org.apache.poi.ss.usermodel.FormulaEvaluator; 8 | import org.apache.poi.ss.usermodel.Row; 9 | import org.apache.poi.xssf.usermodel.XSSFSheet; 10 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 11 | 12 | import t5750.poi.util.Globals; 13 | import t5750.poi.util.TestUtil; 14 | 15 | public class TestExcelFormulaDemo { 16 | public static final String EXCEL_NAME = "testExcelFormulaDemo"; 17 | 18 | public static void main(String[] args) { 19 | XSSFWorkbook workbook = new XSSFWorkbook(); 20 | XSSFSheet sheet = workbook.createSheet("Calculate Simple Interest"); 21 | Row header = sheet.createRow(0); 22 | header.createCell(0).setCellValue("Pricipal"); 23 | header.createCell(1).setCellValue("RoI"); 24 | header.createCell(2).setCellValue("Time"); 25 | header.createCell(3).setCellValue("Interest (P r t)"); 26 | Row dataRow = sheet.createRow(1); 27 | dataRow.createCell(0).setCellValue(14500d); 28 | dataRow.createCell(1).setCellValue(9.25); 29 | dataRow.createCell(2).setCellValue(3d); 30 | dataRow.createCell(3).setCellFormula("A2*B2*C2"); 31 | try { 32 | FileOutputStream out = new FileOutputStream(new File( 33 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 34 | + Globals.SUFFIX_XLSX)); 35 | workbook.write(out); 36 | out.close(); 37 | System.out.println(EXCEL_NAME + Globals.SUFFIX_XLSX 38 | + TestUtil.SUCCESS); 39 | readSheetWithFormula(); 40 | } catch (FileNotFoundException e) { 41 | e.printStackTrace(); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | 47 | public static void readSheetWithFormula() { 48 | try { 49 | FileInputStream file = new FileInputStream(new File( 50 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 51 | + Globals.SUFFIX_XLSX)); 52 | // Create Workbook instance holding reference to .xlsx file 53 | XSSFWorkbook workbook = new XSSFWorkbook(file); 54 | FormulaEvaluator evaluator = workbook.getCreationHelper() 55 | .createFormulaEvaluator(); 56 | // Get first/desired sheet from the workbook 57 | XSSFSheet sheet = workbook.getSheetAt(0); 58 | // Iterate through each rows one by one 59 | Iterator rowIterator = sheet.iterator(); 60 | while (rowIterator.hasNext()) { 61 | Row row = rowIterator.next(); 62 | // For each row, iterate through all the columns 63 | Iterator cellIterator = row.cellIterator(); 64 | while (cellIterator.hasNext()) { 65 | Cell cell = cellIterator.next(); 66 | // If it is formula cell, it will be evaluated otherwise no 67 | // change will happen 68 | switch (evaluator.evaluateInCell(cell).getCellType()) { 69 | case NUMERIC: 70 | System.out.print(cell.getNumericCellValue() + "\t\t"); 71 | break; 72 | case STRING: 73 | System.out.print(cell.getStringCellValue() + "\t\t"); 74 | break; 75 | case FORMULA: 76 | // Not again 77 | break; 78 | } 79 | } 80 | System.out.println(""); 81 | } 82 | file.close(); 83 | } catch (Exception e) { 84 | e.printStackTrace(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/export/TestExcelStylingDemo.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.export; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | 6 | import org.apache.poi.ss.usermodel.*; 7 | import org.apache.poi.ss.util.CellRangeAddress; 8 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 9 | 10 | import t5750.poi.util.Globals; 11 | import t5750.poi.util.TestUtil; 12 | 13 | public class TestExcelStylingDemo { 14 | public static final String EXCEL_NAME = "testExcelStylingDemo"; 15 | 16 | public static void main(String[] args) throws Exception { 17 | Workbook wb = new XSSFWorkbook(); 18 | basedOnValue(wb.createSheet("Value Based formatting")); 19 | formatDuplicates(wb.createSheet("Duplicates formatting")); 20 | shadeAlt(wb.createSheet("Alternate rows")); 21 | expiryInNext30Days(wb.createSheet("Soon Expired Payments")); 22 | // Write the output to a file 23 | FileOutputStream out = new FileOutputStream(TestUtil.DOC_PATH 24 | + File.separator + EXCEL_NAME + Globals.SUFFIX_XLSX); 25 | wb.write(out); 26 | out.close(); 27 | System.out.println(EXCEL_NAME + Globals.SUFFIX_XLSX + TestUtil.SUCCESS); 28 | } 29 | 30 | // Cell value is in between a certain range 31 | static void basedOnValue(Sheet sheet) { 32 | // Creating some random values 33 | sheet.createRow(0).createCell(0).setCellValue(84); 34 | sheet.createRow(1).createCell(0).setCellValue(74); 35 | sheet.createRow(2).createCell(0).setCellValue(50); 36 | sheet.createRow(3).createCell(0).setCellValue(51); 37 | sheet.createRow(4).createCell(0).setCellValue(49); 38 | sheet.createRow(5).createCell(0).setCellValue(41); 39 | SheetConditionalFormatting sheetCF = sheet 40 | .getSheetConditionalFormatting(); 41 | // Condition 1: Cell Value Is greater than 70 (Blue Fill) 42 | ConditionalFormattingRule rule1 = sheetCF 43 | .createConditionalFormattingRule(ComparisonOperator.GT, "70"); 44 | PatternFormatting fill1 = rule1.createPatternFormatting(); 45 | fill1.setFillBackgroundColor(IndexedColors.BLUE.index); 46 | fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); 47 | // Condition 2: Cell Value Is less than 50 (Green Fill) 48 | ConditionalFormattingRule rule2 = sheetCF 49 | .createConditionalFormattingRule(ComparisonOperator.LT, "50"); 50 | PatternFormatting fill2 = rule2.createPatternFormatting(); 51 | fill2.setFillBackgroundColor(IndexedColors.GREEN.index); 52 | fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND); 53 | CellRangeAddress[] regions = { CellRangeAddress.valueOf("A1:A6") }; 54 | sheetCF.addConditionalFormatting(regions, rule1, rule2); 55 | } 56 | 57 | /** 58 | * Use Excel conditional formatting to highlight duplicate entries in a 59 | * column. 60 | */ 61 | static void formatDuplicates(Sheet sheet) { 62 | sheet.createRow(0).createCell(0).setCellValue("Code"); 63 | sheet.createRow(1).createCell(0).setCellValue(4); 64 | sheet.createRow(2).createCell(0).setCellValue(3); 65 | sheet.createRow(3).createCell(0).setCellValue(6); 66 | sheet.createRow(4).createCell(0).setCellValue(3); 67 | sheet.createRow(5).createCell(0).setCellValue(5); 68 | sheet.createRow(6).createCell(0).setCellValue(8); 69 | sheet.createRow(7).createCell(0).setCellValue(0); 70 | sheet.createRow(8).createCell(0).setCellValue(2); 71 | sheet.createRow(9).createCell(0).setCellValue(8); 72 | sheet.createRow(10).createCell(0).setCellValue(6); 73 | SheetConditionalFormatting sheetCF = sheet 74 | .getSheetConditionalFormatting(); 75 | // Condition 1: Formula Is =A2=A1 (White Font) 76 | ConditionalFormattingRule rule1 = sheetCF 77 | .createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1"); 78 | FontFormatting font = rule1.createFontFormatting(); 79 | font.setFontStyle(false, true); 80 | font.setFontColorIndex(IndexedColors.BLUE.index); 81 | CellRangeAddress[] regions = { CellRangeAddress.valueOf("A2:A11") }; 82 | sheetCF.addConditionalFormatting(regions, rule1); 83 | } 84 | 85 | /** 86 | * Use Excel conditional formatting to shade alternating rows on the 87 | * worksheet 88 | */ 89 | static void shadeAlt(Sheet sheet) { 90 | SheetConditionalFormatting sheetCF = sheet 91 | .getSheetConditionalFormatting(); 92 | // Condition 1: Formula Is =A2=A1 (White Font) 93 | ConditionalFormattingRule rule1 = sheetCF 94 | .createConditionalFormattingRule("MOD(ROW(),2)"); 95 | PatternFormatting fill1 = rule1.createPatternFormatting(); 96 | fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index); 97 | fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); 98 | CellRangeAddress[] regions = { CellRangeAddress.valueOf("A1:Z100") }; 99 | sheetCF.addConditionalFormatting(regions, rule1); 100 | } 101 | 102 | /** 103 | * Highlight payments that are due in the next thirty days 104 | */ 105 | static void expiryInNext30Days(Sheet sheet) { 106 | CellStyle style = sheet.getWorkbook().createCellStyle(); 107 | style.setDataFormat((short) BuiltinFormats.getBuiltinFormat("d-mmm")); 108 | sheet.createRow(0).createCell(0).setCellValue("Date"); 109 | sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29"); 110 | sheet.createRow(2).createCell(0).setCellFormula("A2+1"); 111 | sheet.createRow(3).createCell(0).setCellFormula("A3+1"); 112 | for (int rownum = 1; rownum <= 3; rownum++) 113 | sheet.getRow(rownum).getCell(0).setCellStyle(style); 114 | SheetConditionalFormatting sheetCF = sheet 115 | .getSheetConditionalFormatting(); 116 | // Condition 1: Formula Is =A2=A1 (White Font) 117 | ConditionalFormattingRule rule1 = sheetCF 118 | .createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)"); 119 | FontFormatting font = rule1.createFontFormatting(); 120 | font.setFontStyle(false, true); 121 | font.setFontColorIndex(IndexedColors.BLUE.index); 122 | CellRangeAddress[] regions = { CellRangeAddress.valueOf("A2:A4") }; 123 | sheetCF.addConditionalFormatting(regions, rule1); 124 | sheet.getRow(0).createCell(1) 125 | .setCellValue("Dates within the next 30 days are highlighted"); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/export/TestExportExcel.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.export; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | 8 | import org.apache.poi.hssf.usermodel.HSSFFont; 9 | import org.apache.poi.hssf.usermodel.HSSFRichTextString; 10 | import org.apache.poi.hssf.usermodel.HSSFSheet; 11 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 12 | import org.apache.poi.ss.usermodel.IndexedColors; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.core.io.ClassPathResource; 17 | import org.springframework.core.io.Resource; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | import t5750.poi.PoiApplication; 21 | import t5750.poi.util.ExcelExportUtil; 22 | import t5750.poi.util.Globals; 23 | import t5750.poi.util.TestUtil; 24 | 25 | @RunWith(SpringRunner.class) 26 | @SpringBootTest(classes = PoiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 27 | public class TestExportExcel { 28 | @Test 29 | public void exportExcel() throws IOException { 30 | String fileName = "default"; 31 | String docsPath; 32 | Resource resource = new ClassPathResource(Globals.DOC + File.separator 33 | + fileName + Globals.SUFFIX_XLS); 34 | if (resource.exists()) { 35 | docsPath = resource.getFile().getPath(); 36 | } else { 37 | String imagesPath = TestUtil.IMG_PATH + File.separator + "tomcat" 38 | + Globals.SUFFIX_PNG; 39 | ExcelExportUtil.export2003(imagesPath, TestUtil.DOC_PATH); 40 | docsPath = TestUtil.DOC_PATH + File.separator + Globals.EXPORT_BOOK; 41 | } 42 | System.out.println(docsPath); 43 | } 44 | 45 | @Test 46 | public void exportExcelWithStyle() { 47 | try { 48 | String filePath = TestUtil.DOC_PATH + File.separator 49 | + Globals.EXPORT_PRODUCT; 50 | OutputStream os = new FileOutputStream(filePath); 51 | HSSFWorkbook wb = new HSSFWorkbook(); 52 | HSSFSheet sheet = wb.createSheet(Globals.SHEETNAME); 53 | HSSFRichTextString richString = new HSSFRichTextString( 54 | TestUtil.RICH_TEXT_STRING); 55 | HSSFFont font = wb.createFont(); 56 | font.setColor(IndexedColors.BLUE.index); 57 | richString.applyFont(font); 58 | sheet.createRow(0).createCell(0).setCellValue(richString); 59 | wb.write(os); 60 | os.close(); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/test/java/t5750/poi/export/TestExportExcel2007.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.export; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.OutputStream; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.apache.poi.ss.usermodel.CellStyle; 10 | import org.apache.poi.ss.usermodel.IndexedColors; 11 | import org.apache.poi.xssf.usermodel.XSSFCell; 12 | import org.apache.poi.xssf.usermodel.XSSFFont; 13 | import org.apache.poi.xssf.usermodel.XSSFSheet; 14 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 15 | 16 | import t5750.poi.util.Globals; 17 | import t5750.poi.util.TestUtil; 18 | 19 | public class TestExportExcel2007 { 20 | private static final Pattern utfPtrn = Pattern 21 | .compile("_(x[0-9A-Fa-f]{4}_)"); 22 | private static final String UNICODE_CHARACTER_LOW_LINE = "_x005F_"; 23 | 24 | public static void main(String[] args) { 25 | String filePath = TestUtil.DOC_PATH + File.separator 26 | + Globals.EXPORT_2007; 27 | // ExcelExportUtil.export2007(filePath); 28 | export2007WithStyle(filePath); 29 | System.out.println(Globals.EXPORT_2007 + TestUtil.SUCCESS); 30 | } 31 | 32 | /** 33 | * XSSFRichTextString.utfDecode()
34 | * value.contains("_x")
35 | * Pattern.compile("_x([0-9A-Fa-f]{4})_"); 36 | */ 37 | private static void export2007WithStyle(String filePath) { 38 | try { 39 | OutputStream os = new FileOutputStream(filePath); 40 | XSSFWorkbook wb = new XSSFWorkbook(); 41 | XSSFSheet sheet = wb.createSheet(Globals.SHEETNAME); 42 | XSSFCell cell = sheet.createRow(0).createCell(0); 43 | cell.setCellValue(TestUtil.RICH_TEXT_STRINGS[0] 44 | + escape(TestUtil.REGEX + TestUtil.RICH_TEXT_STRINGS[1] 45 | + TestUtil.REGEX) + TestUtil.RICH_TEXT_STRINGS[2]); 46 | CellStyle style = sheet.getWorkbook().createCellStyle(); 47 | XSSFFont font = wb.createFont(); 48 | font.setColor(IndexedColors.BLUE.index); 49 | style.setFont(font); 50 | cell.setCellStyle(style); 51 | // richString.applyFont(font); 52 | wb.write(os); 53 | os.close(); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | /** 60 | * https://bz.apache.org/bugzilla/show_bug.cgi?id=57008 61 | */ 62 | public static String escape(final String value) { 63 | // https://stackoverflow.com/questions/48222502/xssfcell-in-apache-poi-encodes-certain-character-sequences-as-unicode-character 64 | if (value == null) 65 | return null; 66 | StringBuffer buf = new StringBuffer(); 67 | Matcher m = utfPtrn.matcher(value); 68 | int idx = 0; 69 | while (m.find()) { 70 | int pos = m.start(); 71 | if (pos > idx) { 72 | buf.append(value.substring(idx, pos)); 73 | } 74 | buf.append(UNICODE_CHARACTER_LOW_LINE + m.group(1)); 75 | idx = m.end(); 76 | } 77 | buf.append(value.substring(idx)); 78 | return buf.toString(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/test/java/t5750/poi/export/TestWriteExcelDemo.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.export; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.util.Map; 6 | import java.util.Set; 7 | import java.util.TreeMap; 8 | 9 | import org.apache.poi.ss.usermodel.Cell; 10 | import org.apache.poi.ss.usermodel.Row; 11 | import org.apache.poi.xssf.usermodel.XSSFSheet; 12 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 13 | 14 | import t5750.poi.util.Globals; 15 | import t5750.poi.util.TestUtil; 16 | 17 | public class TestWriteExcelDemo { 18 | public static final String EXCEL_NAME = "testExcelDemo"; 19 | 20 | public static void main(String[] args) { 21 | // Blank workbook 22 | XSSFWorkbook workbook = new XSSFWorkbook(); 23 | // Create a blank sheet 24 | XSSFSheet sheet = workbook.createSheet("Employee Data"); 25 | // This data needs to be written (Object[]) 26 | Map data = new TreeMap(); 27 | data.put("1", new Object[] { "ID", "NAME", "LASTNAME" }); 28 | data.put("2", new Object[] { 1, "Amit", "Shukla" }); 29 | data.put("3", new Object[] { 2, "Lokesh", "Gupta" }); 30 | data.put("4", new Object[] { 3, "John", "Adwards" }); 31 | data.put("5", new Object[] { 4, "Brian", "Schultz" }); 32 | // Iterate over data and write to sheet 33 | Set keyset = data.keySet(); 34 | int rownum = 0; 35 | for (String key : keyset) { 36 | Row row = sheet.createRow(rownum++); 37 | Object[] objArr = data.get(key); 38 | int cellnum = 0; 39 | for (Object obj : objArr) { 40 | Cell cell = row.createCell(cellnum++); 41 | if (obj instanceof String) 42 | cell.setCellValue((String) obj); 43 | else if (obj instanceof Integer) 44 | cell.setCellValue((Integer) obj); 45 | } 46 | } 47 | try { 48 | // Write the workbook in file system 49 | FileOutputStream out = new FileOutputStream(new File( 50 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 51 | + Globals.SUFFIX_XLSX)); 52 | workbook.write(out); 53 | out.close(); 54 | System.out.println(EXCEL_NAME + Globals.SUFFIX_XLSX 55 | + TestUtil.SUCCESS); 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/read/TestReadExcel.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.read; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.List; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.core.io.ClassPathResource; 12 | import org.springframework.core.io.Resource; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | import t5750.poi.PoiApplication; 16 | import t5750.poi.service.ExcelService; 17 | import t5750.poi.util.Globals; 18 | 19 | @RunWith(SpringRunner.class) 20 | @SpringBootTest(classes = PoiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 21 | public class TestReadExcel { 22 | @Autowired 23 | private ExcelService readService; 24 | 25 | @Test 26 | public void readExcel() throws IOException { 27 | String fileName = "testRead"; 28 | Resource docsPath = new ClassPathResource(Globals.DOC + File.separator 29 | + fileName + Globals.SUFFIX_XLS); 30 | List> list = readService.readExcel(docsPath.getFile()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/read/TestReadExcelDemo.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.read; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.util.Iterator; 6 | 7 | import org.apache.poi.ss.usermodel.Cell; 8 | import org.apache.poi.ss.usermodel.Row; 9 | import org.apache.poi.xssf.usermodel.XSSFSheet; 10 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 11 | 12 | import t5750.poi.export.TestWriteExcelDemo; 13 | import t5750.poi.util.Globals; 14 | import t5750.poi.util.TestUtil; 15 | 16 | public class TestReadExcelDemo { 17 | public static void main(String[] args) { 18 | try { 19 | FileInputStream file = new FileInputStream(new File( 20 | TestUtil.DOC_PATH + File.separator 21 | + TestWriteExcelDemo.EXCEL_NAME 22 | + Globals.SUFFIX_XLSX)); 23 | // Create Workbook instance holding reference to .xlsx file 24 | XSSFWorkbook workbook = new XSSFWorkbook(file); 25 | // Get first/desired sheet from the workbook 26 | XSSFSheet sheet = workbook.getSheetAt(0); 27 | // Iterate through each rows one by one 28 | Iterator rowIterator = sheet.iterator(); 29 | while (rowIterator.hasNext()) { 30 | Row row = rowIterator.next(); 31 | // For each row, iterate through all the columns 32 | Iterator cellIterator = row.cellIterator(); 33 | while (cellIterator.hasNext()) { 34 | Cell cell = cellIterator.next(); 35 | // Check the cell type and format accordingly 36 | switch (cell.getCellType()) { 37 | case NUMERIC: 38 | System.out.print(cell.getNumericCellValue() + "\t"); 39 | break; 40 | case STRING: 41 | System.out.print(cell.getStringCellValue() + "\t"); 42 | break; 43 | } 44 | } 45 | System.out.println(""); 46 | } 47 | file.close(); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/replace/TestExcelReplace.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.replace; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import t5750.poi.command.ExcelReplaceDataVO; 9 | import t5750.poi.util.ExcelReplaceUtil; 10 | import t5750.poi.util.Globals; 11 | import t5750.poi.util.TestUtil; 12 | 13 | /** 14 | * 参考地址:http://yaoh6688.iteye.com/blog/1152273 15 | */ 16 | public class TestExcelReplace { 17 | public static final String EXCEL_NAME = "replaceTemplate"; 18 | 19 | public static void main(String[] args) throws FileNotFoundException { 20 | List datas = new ArrayList(); 21 | // 找到第14行第2列的company,用"XXX有限公司"替换掉company 22 | ExcelReplaceDataVO voCompany = new ExcelReplaceDataVO(); 23 | voCompany.setRow(13); 24 | voCompany.setColumn(1); 25 | voCompany.setKey("company"); 26 | voCompany.setValue("XXX有限公司"); 27 | // 找到第5行第2列的content,用"替换的内容"替换掉content 28 | ExcelReplaceDataVO voContent = new ExcelReplaceDataVO(); 29 | voContent.setRow(4); 30 | voContent.setColumn(1); 31 | voContent.setKey("content"); 32 | voContent.setValue("替换的内容"); 33 | datas.add(voCompany); 34 | datas.add(voContent); 35 | // replaceTemplate.xls为Excel模板文件,d:\\replaceTemplate*.xls为程序根据Excel模板文件生成的新文件 36 | ExcelReplaceUtil.replaceModel(datas, 37 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 38 | + Globals.SUFFIX_XLS, 39 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 40 | + System.currentTimeMillis() + Globals.SUFFIX_XLS); 41 | System.out.println(EXCEL_NAME + Globals.SUFFIX_XLSX + TestUtil.SUCCESS); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/template/TestTemplate.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.template; 2 | 3 | import java.io.File; 4 | import java.util.Date; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import t5750.poi.util.DateUtil; 9 | import t5750.poi.util.ExcelTemplateUtil; 10 | import t5750.poi.util.Globals; 11 | import t5750.poi.util.TestUtil; 12 | 13 | /** 14 | * 参考地址:http://mylfd.iteye.com/blog/1982101 15 | */ 16 | public class TestTemplate { 17 | public static final String EXCEL_NAME = "template"; 18 | 19 | public static void main(String[] args) { 20 | ExcelTemplateUtil excel = ExcelTemplateUtil.getInstance() 21 | .readTemplatePath( 22 | TestUtil.DOC_PATH + File.separator + EXCEL_NAME 23 | + Globals.SUFFIX_XLS); 24 | for (int i = 0; i < 5; i++) { 25 | excel.creatNewRow(); 26 | excel.createNewCol("Col" + i); 27 | excel.createNewCol(i); 28 | excel.createNewCol(i); 29 | } 30 | Map datas = new HashMap(); 31 | datas.put("title", "POI Repositories"); 32 | datas.put("content", "the Java API for Microsoft Documents"); 33 | datas.put("date", DateUtil.format(new Date())); 34 | excel.replaceFind(datas); 35 | excel.insertSer(); 36 | excel.writeToFile(TestUtil.DOC_PATH + File.separator + EXCEL_NAME 37 | + System.currentTimeMillis() + Globals.SUFFIX_XLS); 38 | System.out.println(EXCEL_NAME + Globals.SUFFIX_XLSX + TestUtil.SUCCESS); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/t5750/poi/util/TestUtil.java: -------------------------------------------------------------------------------- 1 | package t5750.poi.util; 2 | 3 | public class TestUtil { 4 | /** 5 | * poi\target\classes\doc 6 | */ 7 | public static final String DOC_PATH = Globals.DOC_PATH.replace( 8 | "test-classes", "classes"); 9 | public static final String IMG_PATH = Globals.IMG_PATH.replace( 10 | "test-classes", "classes"); 11 | public static final String SUCCESS = " written successfully..."; 12 | public static final String RICH_TEXT_STRING = "o9qAGtxS7K25ItIvnNXd_xBcCe_0"; 13 | public static final String REGEX = "_"; 14 | public static final String[] RICH_TEXT_STRINGS = RICH_TEXT_STRING 15 | .split(REGEX); 16 | } --------------------------------------------------------------------------------