步骤 1: 引入依赖
在pom.xml
文件中添加EasyExcel
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
步骤2: 准备xlsm模板
首先,需要在Excel中创建一个包含下拉多选的模板,并保存为.xlsm格式。具体步骤如下:
- 打开Excel,创建一个新的工作簿。
- 在第二个Sheet(Sheet2)的第一列(A列)填充下拉列表的选项数据。
- 在需要下拉多选的单元格区域,设置数据验证(Data Validation),使用来源(Source)指向Sheet2的选项数据范围。
- 使用VBA代码实现多选功能。在Excel中按
Alt + F11
打开VBA编辑器,选择工作簿(ThisWorkbook),然后将以下代码粘贴进去:
Sub Worksheet_Change(ByVal Target As Range)
'让数据有效性选择 可以多选,不可重复
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
If Target.Count > 1 Then GoTo exitHandler
On Error Resume Next
Set rngDV = Cells.SpecialCells(xlCellTypeAllValidation)
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Intersect(Target, rngDV) Is Nothing Then
'do nothing
Else
Application.EnableEvents = False
newVal = Target.Value
If Target.Column = 3 Then '数字是你想要多选的列是多少,多个用or连接。
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If oldVal = "" Then
Else
If newVal = "" Then
Else '去除重复的字段
If InStr(1, oldVal, newVal) <> 0 Then
If InStr(1, oldVal, newVal) + Len(newVal) - 1 = Len(oldVal) Then '最后一个选项重复
Target.Value = Left(oldVal, Len(oldVal) - Len(newVal) - 1)
Else
Target.Value = Replace(oldVal, newVal & "、", "") '不是最后一个选项重复的时候处理逗号
End If
Else '不是重复选项就视同增加选项
Target.Value = oldVal _
& "、" & newVal '可以是任意符号隔开
End If
End If
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
步骤 3: 编写Spring Boot控制器
使用EasyExcel读取模板,并结合Apache POI设置下拉选项。然后,通过Spring Boot控制器生成并下载Excel文件。
以下是完整的Spring Boot控制器示例:
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@RestController
public class ExcelController {
@GetMapping("/download/template")
public void downloadTemplate(HttpServletResponse response) throws IOException {
try (InputStream inputStream = new ClassPathResource("templates/multiSelect.xlsm").getInputStream()) {
// 动态下拉数据
List<String> orgNameList = Arrays.asList("组1","组2");
// 设置响应头
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
String format = DateUtil.format(new Date(), "yyyyMMddHHmmss");
String fileName = URLEncoder.encode("test"+ format, "UTF-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName + ".xlsm");
// 创建 ExcelWriter 并设置 SpinnerWriteHandler
ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream())
.withTemplate(inputStream);
// 写入空数据以应用模板和处理器
try (ExcelWriter excelWriter = writerBuilder.build()) {
// 写入第二个 Sheet,将 orgNameList 写入第一列
WriteSheet secondSheet = EasyExcel.writerSheet(1).build();
List<List<String>> data = orgNameList.stream()
.map(name -> {
List<String> row = new ArrayList<>();
row.add(name);
return row;
})
.collect(Collectors.toList());
excelWriter.write(data, secondSheet);
// 写入第一个 Sheet
WriteSheet firstSheet = EasyExcel.writerSheet(0).build();
excelWriter.write(new ArrayList<>(), firstSheet); // 提供一个空列表以避免歧义
}
} catch (IOException e) {
throw new RuntimeException("Failed to download the template", e);
}
}
}
效果图
源码下载地址: katriinatavi/springboot-excel