目录
目录
二、实现复杂表头的自定义excel导出插件
总结
前言
最近兴趣使然,研究了一下如何搭建maven私服,然后就想试一下上传自定义插件的使用,于是乎就封装了一个简易的excel导出插件,通过自定义注解、泛型和反射实现。下面就来记录一下我的实现思路和最终实现效果。
一、maven私服怎么搭建?
我也是通过网上的教程,期间也踩过各种坑,本人实在win10上搭建的,首先要先下载安装nexus,这个官网下载失败,好像要翻墙才能,没试过,这里提供一个联想乐云下载地址,下载之后直接解压就行,进入nexus目录下的G:\nexus-maven\nexus-3.30.1-01-win64\nexus-3.30.1-01\bin目录cmd运行 nexus.exe /run 就可以启动,默认端口是8081,同时也是可以修改的,在目录G:\nexus-maven\nexus-3.30.1-01-win64\nexus-3.30.1-01\etc\nexus-default.properties中
##
# Jetty section
application-port=8081
application-host=0.0.0.0
nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-requestlog.xml
nexus-context-path=/
# Nexus section
nexus-edition=nexus-pro-edition
nexus-features=\
nexus-pro-feature
nexus.hazelcast.discovery.isEnabled=true
运行要等一会之后访问http://127.0.0.1:8081/
admin的初始密码在G:\nexus-maven\nexus-3.30.1-01-win64\sonatype-work\nexus3\admin.password文件中
安装为服务的方法是在G:\nexus-maven\nexus-3.30.1-01-win64\nexus-3.30.1-01\bin中cmd下管理员运行nexus.exe /install 来安装为系统服务。
下面就是配置maven的setting.xml 分享我的
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
| This is the configuration file for Maven. It can be specified at two levels:
|
| 1. User Level. This settings.xml file provides configuration for a single user,
| and is normally provided in ${user.home}/.m2/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -s /path/to/user/settings.xml
|
| 2. Global Level. This settings.xml file provides configuration for all Maven
| users on a machine (assuming they're all using the same Maven
| installation). It's normally provided in
| ${maven.conf}/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -gs /path/to/global/settings.xml
|
| The sections in this sample file are intended to give you a running start at
| getting the most out of your Maven installation. Where appropriate, the default
| values (values used when the setting is not specified) are provided.
|
|-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>H:\maven\resouce</localRepository>
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->
<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false
<offline>false</offline>
-->
<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>
<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>
<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- 私服密码 -->
<server>
<!-- 这里的id可以随意取,但是我们在pom.xml中配置的id要与此一致 -->
<!-- release正式版本 -->
<id>local-release</id>
<username>admin</username>
<password>123456</password>
</server>
<server>
<!-- 这里的id可以随意取,但是我们在pom.xml中配置的id要与此一致 -->
<!-- snapshot快照版本 -->
<id>local-snapshot</id>
<username>admin</username>
<password>123456</password>
</server>
</servers>
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
<mirrors>
<mirror>
<!--该镜像的唯一标识符。id用来区分不同的mirror元素。 -->
<id>nexus</id>
<!--此处配置所有的构建均从私有仓库中下载 *代表所有,也可以写central -->
<mirrorOf>*</mirrorOf>
<name>central repository</name>
<!--该镜像的URL。构建系统会优先考虑使用该URL,而非使用默认的服务器URL。 -->
<url>http://127.0.0.1:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<!-- profiles
| This is a list of profiles which can be activated in a variety of ways, and which can modify
| the build process. Profiles provided in the settings.xml are intended to provide local machine-
| specific paths and repository locations which allow the build to work in the local environment.
|
| For example, if you have an integration testing plugin - like cactus - that needs to know where
| your Tomcat instance is installed, you can provide a variable here such that the variable is
| dereferenced during the build process to configure the cactus plugin.
|
| As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
| section of this document (settings.xml) - will be discussed later. Another way essentially
| relies on the detection of a system property, either matching a particular value for the property,
| or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
| value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
| Finally, the list of active profiles can be specified directly from the command line.
|
| NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
| repositories, plugin repositories, and free-form properties to be used as configuration
| variables for plugins in the POM.
|
|-->
<profiles>
<profile>
<id>nexus</id>
<!--远程仓库列表,它是Maven用来填充构建系统本地仓库所使用的一组远程项目。 -->
<repositories>
<!--发布版本仓库-->
<repository>
<id>nexus</id>
<!--地址是nexus中repository(Releases/Snapshots)中对应的地址-->
<url>http://127.0.0.1:8081/repository/maven-public/</url>
<!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<!--激活配置-->
<activeProfiles>
<!--profile下的id-->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
在maven项目的pom文件一定要添加这个
<project>
<!-- 配置 nexus -->
<distributionManagement>
<repository>
<id>local-release</id>
<name>msqAutoExcel</name>
<url>http://127.0.0.1:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>local-snapshot</id>
<name>msqAutoExcel</name>
<url>http://127.0.0.1:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
</project>
二、实现复杂表头的自定义excel导出插件
1.首先创建maven项目
excel导出的插件使用到的 是poi,所以pom中引入
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!--Apache POI --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>servlet-api</artifactId> <version>6.0.53</version> </dependency>
2.创建自定义注解
package com.home.msq.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MsqField {
/**
* 表格顶部标题
* @return
*/
String[] title() default {};
/**
* 合并单元格位置{0,0,0,0}
* @return
*/
int[] index() default{};
}
package com.home.msq.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MsqTable {
/**
* sheet名称
* @return
*/
String sheet() default "";
/**
* 文件名称
* @return
*/
String fileName() default "";
}
3.poi具体实现
package com.home.msq;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.home.msq.annotation.MsqField;
import com.home.msq.annotation.MsqTable;
//clean deploy -X
/**
* 导出Excel
*
* @author liuyazhuang
*
* @param <T>
*/
public class ExportExcelUtil<T> {
private Class clzz;
public ExportExcelUtil(Class c) {
clzz = c;
}
/**
* <p>
* 通用Excel导出方法,利用反射机制遍历对象的所有字段,将数据写入Excel文件中 <br>
* 此版本生成2007以上版本的文件 (文件后缀:xlsx)
* </p>
*
* @param title 表格标题名
* @param headers 表格头部标题集合
* @param dataset 需要显示的数据集合,集合中一定要放置符合JavaBean风格的类的对象。此方法支持的
* JavaBean属性的数据类型有基本数据类型及String,Date
* @param out 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中
* @param pattern 如果有时间数据,设定输出格式。默认为"yyyy-MM-dd hh:mm:ss"
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void exportExcel2007(Collection<T> dataset,HttpServletResponse response) throws Exception {
// 声明一个工作薄
@SuppressWarnings("resource")
XSSFWorkbook workbook = new XSSFWorkbook();
String title="sheet1";
String fileName="";
// 获取类注解
if(clzz.isAnnotationPresent(MsqTable.class)){
// System.out.println(clzz.getAnnotation(MsqTable.class).value());
title = ((MsqTable) clzz.getAnnotation(MsqTable.class)).sheet();
fileName = ((MsqTable) clzz.getAnnotation(MsqTable.class)).fileName();
}
///
fileName = fileName + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xlsx";
String headStr = "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8") + ";filename*=utf-8''" + java.net.URLEncoder.encode(fileName, "UTF-8");
response.setContentType("APPLICATION/OCTET-STREAM"); // octet-stream 自动匹配文件类型
response.setHeader("Content-Disposition", headStr); // 激活下载框
// 生成一个表格
XSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
// 生成一个样式
XSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
//style.setFillForegroundColor(new XSSFColor(java.awt.Color.gray));
style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
// 生成一个字体
XSSFFont font = workbook.createFont();
font.setBold(true);
font.setFontName("宋体");
font.setColor(IndexedColors.BLACK.getIndex());
font.setFontHeightInPoints((short) 11);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
XSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(IndexedColors.WHITE.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
style2.setVerticalAlignment(VerticalAlignment.CENTER);
style2.setAlignment(HorizontalAlignment.CENTER);
// 生成另一个字体
XSSFFont font2 = workbook.createFont();
//font2.setBold(true);
font2.setColor(IndexedColors.GREY_80_PERCENT.getIndex());
// 把字体应用到当前的样式
style2.setFont(font2);
setTitle(sheet);
// 产生表格标题行
XSSFRow row ;
XSSFCell cellHeader;
/* for (int i = 0; i < headers.length; i++) {
cellHeader = row.createCell(i);
cellHeader.setCellStyle(style);
cellHeader.setCellValue(new XSSFRichTextString(headers[i]));
}*/
// 获取类变量注解:
Field[] msqFields = clzz.getDeclaredFields();
//getNum
int num = getNum();
String[][] headers = new String[num][msqFields.length];
for(int k=0;k<num;k++) {
String[] bts = new String[msqFields.length];
for (int i = 0; i < msqFields.length; i++) {
Field f = msqFields[i];
if(f.isAnnotationPresent(MsqField.class)){
// System.out.print(f.getAnnotation(MsqField.class).title() + ",");
String[] titles = f.getAnnotation(MsqField.class).title();
for(int j=0;j<titles.length;j++) {
if(j==k) {
bts[i]=titles[k];
}
}
}
}
headers[k]=bts;
}
for (int i = 0; i < headers.length; i++) {
// 产生表格标题行
row = sheet.createRow(i);
String[] bts = headers[i];
for(int j=0;j<bts.length;j++) {
cellHeader = row.createCell(j);
cellHeader.setCellStyle(style);
cellHeader.setCellValue(new XSSFRichTextString(bts[j]));
}
}
// 遍历集合数据,产生数据行
Iterator<T> it = dataset.iterator();
int index = getNum()-1;
T t;
Field[] fields;
Field field;
XSSFRichTextString richString;
Pattern p = Pattern.compile("^//d+(//.//d+)?$");
Matcher matcher;
String fieldName;
String getMethodName;
XSSFCell cell;
Class tCls;
Method getMethod;
Object value;
String textValue;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
t = it.next();
// 利用反射,根据JavaBean属性的先后顺序,动态调用getXxx()方法得到属性值
fields = t.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
cell = row.createCell(i);
cell.setCellStyle(style2);
field = fields[i];
fieldName = field.getName();
getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
tCls = t.getClass();
getMethod = tCls.getMethod(getMethodName, new Class[] {});
value = getMethod.invoke(t, new Object[] {});
// 判断值的类型后进行强制类型转换
textValue = null;
if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Float) {
textValue = String.valueOf(value);
cell.setCellValue(textValue);
} else if (value instanceof Double) {
textValue = String.valueOf(value);
cell.setCellValue(textValue);
} else if (value instanceof Long) {
cell.setCellValue((Long) value);
}
if (value instanceof Boolean) {
textValue = "是";
if (!(Boolean) value) {
textValue = "否";
}
} else if (value instanceof Date) {
textValue = sdf.format((Date) value);
} else {
// 其它数据类型都当作字符串简单处理
if (value != null) {
textValue = value.toString();
}
}
if (textValue != null) {
matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
richString = new XSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} finally {
// 清理资源
}
}
}
try {
workbook.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private Integer getNum() {
Field[] msqFields = clzz.getDeclaredFields();
for (int i = 0; i < msqFields.length; i++) {
Field f = msqFields[i];
if(f.isAnnotationPresent(MsqField.class)){
// System.out.print(f.getAnnotation(MsqField.class).title() + ",");
String[] titles = f.getAnnotation(MsqField.class).title();
return titles.length;
}
}
return null;
}
private void setTitle(XSSFSheet sheet) {
//指定合并开始行、合并结束行 合并开始列、合并结束列
Field[] fields = clzz.getDeclaredFields();
for (Field f : fields) {
if(f.isAnnotationPresent(MsqField.class)){
int[] a = f.getAnnotation(MsqField.class).index();
if(a.length>0) {
CellRangeAddress hang = new CellRangeAddress(a[0],a[1], a[2], a[3]);
//添加要合并地址到表格
sheet.addMergedRegion(hang);
}
}
}
}
}
4.上传插件到私服
直接maven命令deploy 运行上传到私服上后可以查看
5.创建springboot项目引入刚刚上传的插件并使用
springBoot项目pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.jinge</groupId>
<artifactId>dome</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dome</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.home.msq</groupId>
<artifactId>msqExcel</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
实体类如下:
package com.jinge.lh.po;
import com.home.msq.annotation.MsqField;
import com.home.msq.annotation.MsqTable;
import lombok.Data;
@Data
@MsqTable(sheet = "测试一下",fileName = "学生信息")
public class Dome {
@MsqField(title = {"用户姓名",""},index = {0,1,0,0})
private String userName;
@MsqField(title ={"用户年龄",""},index= {0,1,1,1})
private String age;
@MsqField(title ={"用户生日",""},index= {0,1,2,2})
private String birthday;
@MsqField(title ={"课程","语文分数"},index= {})
private String ywNum;
@MsqField(title ={"","数学分数"},index= {0,0,3,4})
private String sxNum;
}
controller如下:
package com.jinge.lh.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.home.msq.ExportExcelUtil;
import com.jinge.lh.po.Dome;
@Controller
@RequestMapping("/")
public class DomeController {
@RequestMapping("get")
public void get(HttpServletResponse response) {
List<Dome> domes = new ArrayList<Dome>();
for(int i=0;i<10;i++) {
Dome d = new Dome();
d.setUserName("姓名"+i);
d.setAge("9"+i);
d.setBirthday("10-1"+i);
d.setSxNum("5"+i);
d.setYwNum("9"+i);
domes.add(d);
}
try {
ExportExcelUtil<Dome> excelUtil = new ExportExcelUtil<Dome>(Dome.class);
excelUtil.exportExcel2007(domes, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
浏览器访问后就可以直接下载excel了
关于poi的合并单元格我来解释一下{0,0,0,0} 前面两个指的是X轴坐标,后面两个指的是Y轴坐标,上面实体类中{0,1,0,0}指的就是合并实际表格的1、2行,1的坐标0,2的坐标1,A的坐标就是Y轴的0,意思就是合并0列的第一行和第二行。
总结
所谓技术就是不停的学习并实践才能更好的理解运用,当然有好的想法就要动手去实现。不然空想是没有用的。