如果你经常做数据分析报表,一定见过这种场景:一个Excel表格里塞满了数据,老板想看某个地区、某个月份的数据,你得手动筛选半天。如果有那种点一下按钮就能切换视图的功能就好了——这就是切片器要解决的问题。
切片器是Excel 2010引入的一个超实用功能,本质上就是可视化的筛选器。今天我来分享一下如何用Java代码给Excel添加切片器,让你的报表从"静态表格"变成"交互式仪表板"。
简单讲,切片器就是个浮动的筛选按钮面板。比如你有个销售数据表,包含产品、地区、时间等字段。传统做法是用自动筛选,但切片器更直观:
比起传统的下拉筛选,切片器的优势在于:
好了,理论说够了,直接上代码。
在开始前,使用以下代码从 Maven 安装 Spire.XLS for Java:
<repositories>
<repository>
<id>com.e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
<version>14.12.0</version>
</dependency>
</dependencies>最基础的用法,先有个数据表,然后基于它创建切片器。
import com.spire.xls.*;
import com.spire.xls.core.IListObject;
import com.spire.xls.core.spreadsheet.slicer.*;
public class CreateSlicerFromTable {
public static void main(String[] args) {
Workbook wb = new Workbook();
Worksheet worksheet = wb.getWorksheets().get(0);
// 准备示例数据
worksheet.getCellRange("A1").setValue("水果");
worksheet.getCellRange("A2").setValue("葡萄");
worksheet.getCellRange("A3").setValue("蓝莓");
worksheet.getCellRange("A4").setValue("猕猴桃");
worksheet.getCellRange("A5").setValue("樱桃");
worksheet.getCellRange("B1").setValue("年份");
worksheet.getCellRange("B2").setValue2(2020);
worksheet.getCellRange("B3").setValue2(2020);
worksheet.getCellRange("B4").setValue2(2021);
worksheet.getCellRange("B5").setValue2(2021);
worksheet.getCellRange("C1").setValue("销量");
worksheet.getCellRange("C2").setValue2(50);
worksheet.getCellRange("C3").setValue2(60);
worksheet.getCellRange("C4").setValue2(70);
worksheet.getCellRange("C5").setValue2(80);
// 创建表格对象
IListObject table = worksheet.getListObjects()
.create("销售表", worksheet.getCellRange("A1:C5"));
// 获取切片器集合
XlsSlicerCollection slicers = worksheet.getSlicers();
// 基于表格的"水果"列创建切片器(第0列)
int index = slicers.add(table, "E2", 0);
// 获取切片器对象并设置样式
XlsSlicer xlsSlicer = slicers.get(index);
xlsSlicer.setName("FruitSlicer");
xlsSlicer.setStyleType(SlicerStyleType.SlicerStyleLight2);
wb.saveToFile("table_slicer.xlsx", ExcelVersion.Version2013);
wb.dispose();
}
}运行后打开Excel,你会看到右侧多了个浮动面板,上面有"葡萄"、"蓝莓"等按钮。点哪个就筛选哪个,超级直观。
实际工作中,切片器更多是和透视表配合使用。透视表做汇总,切片器做筛选,绝配。
import com.spire.xls.*;
import com.spire.xls.collections.PivotTablesCollection;
import com.spire.xls.core.IPivotField;
import com.spire.xls.core.spreadsheet.slicer.*;
public class CreateSlicerFromPivotTable {
public static void main(String[] args) {
Workbook wb = new Workbook();
Worksheet worksheet = wb.getWorksheets().get(0);
// 准备数据(和上面一样)
worksheet.getCellRange("A1").setValue("水果");
worksheet.getCellRange("A2").setValue("葡萄");
worksheet.getCellRange("A3").setValue("蓝莓");
worksheet.getCellRange("A4").setValue("猕猴桃");
worksheet.getCellRange("A5").setValue("樱桃");
worksheet.getCellRange("A6").setValue("葡萄");
worksheet.getCellRange("A7").setValue("蓝莓");
worksheet.getCellRange("B1").setValue("年份");
worksheet.getCellRange("B2").setValue2(2020);
worksheet.getCellRange("B3").setValue2(2020);
worksheet.getCellRange("B4").setValue2(2020);
worksheet.getCellRange("B5").setValue2(2021);
worksheet.getCellRange("B6").setValue2(2021);
worksheet.getCellRange("B7").setValue2(2021);
worksheet.getCellRange("C1").setValue("销量");
worksheet.getCellRange("C2").setValue2(50);
worksheet.getCellRange("C3").setValue2(60);
worksheet.getCellRange("C4").setValue2(70);
worksheet.getCellRange("C5").setValue2(80);
worksheet.getCellRange("C6").setValue2(90);
worksheet.getCellRange("C7").setValue2(100);
// 创建透视表缓存
CellRange dataRange = worksheet.getCellRange("A1:C7");
PivotCache cache = wb.getPivotCaches().add(dataRange);
// 在A12位置创建透视表
PivotTable pt = worksheet.getPivotTables()
.add("销售透视表", worksheet.getCellRange("A12"), cache);
// 配置透视表字段
PivotField pf = (PivotField)pt.getPivotFields().get("水果");
pf.setAxis(AxisTypes.Row); // 行区域
PivotField pf2 = (PivotField)pt.getPivotFields().get("年份");
pf2.setAxis(AxisTypes.Column); // 列区域
// 添加数据字段(求和)
pt.getDataFields().add(
pt.getPivotFields().get("销量"),
"总销量",
SubtotalTypes.Sum
);
// 设置透视表样式
pt.setBuiltInStyle(PivotBuiltInStyles.PivotStyleMedium10);
pt.calculateData();
// 创建第一个切片器(基于"水果"字段)
XlsSlicerCollection slicers = worksheet.getSlicers();
int index = slicers.add(pt, "E12", 0);
XlsSlicer fruitSlicer = slicers.get(index);
fruitSlicer.setName("FruitFilter");
fruitSlicer.setWidth(150);
fruitSlicer.setHeight(120);
fruitSlicer.setStyleType(SlicerStyleType.SlicerStyleLight2);
// 锁定位置,防止被误拖动
fruitSlicer.isPositionLocked(true);
// 创建第二个切片器(基于"年份"字段)
IPivotField yearField = pt.getPivotFields().get("年份");
int index2 = slicers.add(pt, "I12", yearField);
XlsSlicer yearSlicer = slicers.get(index2);
yearSlicer.setName("YearFilter");
yearSlicer.setStyleType(SlicerStyleType.SlicerStyleLight3);
yearSlicer.setRowHeight(35);
wb.saveToFile("pivot_slicer.xlsx", ExcelVersion.Version2013);
wb.dispose();
}
}这个例子创建了两个切片器:一个筛选水果,一个筛选择年份。两个切片器联动控制同一个透视表,用户体验非常好。
默认的切片器样式可能不符合你的UI设计,可以自定义:
import com.spire.xls.*;
import com.spire.xls.core.spreadsheet.slicer.*;
public class CustomizeSlicer {
public static void main(String[] args) {
Workbook wb = new Workbook();
wb.loadFromFile("existing_with_slicer.xlsx");
Worksheet worksheet = wb.getWorksheets().get(0);
XlsSlicerCollection slicers = worksheet.getSlicers();
// 获取第一个切片器
XlsSlicer slicer = slicers.get(0);
// 修改标题
slicer.setCaption("产品筛选器");
// 设置尺寸
slicer.setWidth(200);
slicer.setHeight(150);
// 设置每行显示的按钮数
slicer.setNumberOfColumns(2);
// 设置按钮高度
slicer.setRowHeight(40);
// 选择深色主题样式
slicer.setStyleType(SlicerStyleType.SlicerStyleDark4);
// 是否显示标题
slicer.isShowCaption(true);
wb.saveToFile("customized_slicer.xlsx", ExcelVersion.Version2013);
wb.dispose();
}
}可用的样式类型:
SlicerStyleLight1 ~ SlicerStyleLight6:浅色主题SlicerStyleMedium1 ~ SlicerStyleMedium2:中等对比度SlicerStyleDark1 ~ SlicerStyleDark6:深色主题根据你们的UI风格选择合适的配色。
有时候需要预设筛选条件,比如默认只显示某个地区的数据:
import com.spire.xls.*;
import com.spire.xls.core.spreadsheet.slicer.*;
public class ControlSlicerSelection {
public static void main(String[] args) {
Workbook wb = new Workbook();
wb.loadFromFile("with_slicer.xlsx");
Worksheet worksheet = wb.getWorksheets().get(0);
XlsSlicerCollection slicers = worksheet.getSlicers();
XlsSlicer slicer = slicers.get(0);
// 获取切片器的缓存项集合
XlsSlicerCacheItemCollection items =
slicer.getSlicerCache().getSlicerCacheItems();
// 遍历所有项,只选中"华东"
for (int i = 0; i < items.getCount(); i++) {
XlsSlicerCacheItem item = items.get(i);
String value = item.getDisplayValue();
if ("华东".equals(value)) {
item.isSelected(true); // 选中
} else {
item.isSelected(false); // 取消选中
}
}
// 设置交叉筛选类型
XlsSlicerCache cache = slicer.getSlicerCache();
// 选项1:显示所有项(包括无数据的)
cache.setCrossFilterType(SlicerCacheCrossFilterType.ShowItemsWithNoData);
// 选项2:有数据的排前面
// cache.setCrossFilterType(SlicerCacheCrossFilterType.ShowItemsWithDataAtTop);
wb.saveToFile("filtered_slicer.xlsx", ExcelVersion.Version2013);
wb.dispose();
}
}应用场景:打开报表时默认显示本月数据、根据用户权限预设筛选条件等。
如果需要审计或记录切片器配置,可以读取其属性:
import com.spire.xls.*;
import com.spire.xls.core.spreadsheet.slicer.*;
import java.io.FileWriter;
public class ReadSlicerInfo {
public static void main(String[] args) throws Exception {
Workbook wb = new Workbook();
wb.loadFromFile("with_slicers.xlsx");
Worksheet worksheet = wb.getWorksheets().get(0);
XlsSlicerCollection slicers = worksheet.getSlicers();
System.out.println("切片器数量:" + slicers.getCount());
for (int i = 0; i < slicers.getCount(); i++) {
XlsSlicer slicer = slicers.get(i);
System.out.println("\n=== 切片器 " + (i+1) + " ===");
System.out.println("名称:" + slicer.getName());
System.out.println("标题:" + slicer.getCaption());
System.out.println("宽度:" + slicer.getWidth());
System.out.println("高度:" + slicer.getHeight());
System.out.println("每行列数:" + slicer.getNumberOfColumns());
System.out.println("按钮高度:" + slicer.getRowHeight());
System.out.println("显示标题:" + slicer.isShowCaption());
System.out.println("位置锁定:" + slicer.isPositionLocked());
// 读取关联的数据源
XlsSlicerCache cache = slicer.getSlicerCache();
System.out.println("数据源:" + cache.getSourceName());
// 读取当前选中状态
XlsSlicerCacheItemCollection items = cache.getSlicerCacheItems();
System.out.print("已选项:");
for (int j = 0; j < items.getCount(); j++) {
if (items.get(j).isSelected()) {
System.out.print(items.get(j).getDisplayValue() + " ");
}
}
System.out.println();
}
wb.dispose();
}
}这个功能在做报表模板检查、自动化测试时很有用。
不需要的时候可以删除:
import com.spire.xls.*;
import com.spire.xls.core.spreadsheet.slicer.*;
public class RemoveSlicer {
public static void main(String[] args) {
Workbook wb = new Workbook();
wb.loadFromFile("with_slicers.xlsx");
Worksheet worksheet = wb.getWorksheets().get(0);
XlsSlicerCollection slicers = worksheet.getSlicers();
// 方式1:删除指定位置的切片器
if (slicers.getCount() > 0) {
slicers.removeAt(0); // 删除第一个
}
// 方式2:清空所有切片器
// slicers.clear();
wb.saveToFile("without_slicers.xlsx", ExcelVersion.Version2013);
wb.dispose();
}
}最后来个完整的例子,创建一个带多个切片器的销售分析仪表板:
import com.spire.xls.*;
import com.spire.xls.core.IPivotField;
import com.spire.xls.core.spreadsheet.slicer.*;
import java.util.*;
public class SalesDashboard {
static class SaleRecord {
String region;
String product;
String month;
double amount;
SaleRecord(String region, String product, String month, double amount) {
this.region = region;
this.product = product;
this.month = month;
this.amount = amount;
}
}
public static void main(String[] args) {
Workbook wb = new Workbook();
Worksheet sheet = wb.getWorksheets().get(0);
// 1. 准备销售数据
List<SaleRecord> records = Arrays.asList(
new SaleRecord("华东", "产品A", "1月", 10000),
new SaleRecord("华东", "产品B", "1月", 15000),
new SaleRecord("华北", "产品A", "1月", 8000),
new SaleRecord("华北", "产品B", "2月", 12000),
new SaleRecord("华南", "产品A", "2月", 9000),
new SaleRecord("华南", "产品B", "2月", 11000),
new SaleRecord("华东", "产品A", "3月", 13000),
new SaleRecord("华北", "产品B", "3月", 14000)
);
// 写入表头
String[] headers = {"地区", "产品", "月份", "销售额"};
for (int i = 0; i < headers.length; i++) {
sheet.getCellRange(1, i + 1).setValue(headers[i]);
}
// 写入数据
for (int i = 0; i < records.size(); i++) {
SaleRecord r = records.get(i);
int row = i + 2;
sheet.getCellRange(row, 1).setValue(r.region);
sheet.getCellRange(row, 2).setValue(r.product);
sheet.getCellRange(row, 3).setValue(r.month);
sheet.getCellRange(row, 4).setNumberValue(r.amount);
}
// 2. 创建透视表
CellRange dataRange = sheet.getCellRange("A1:D" + (records.size() + 1));
PivotCache cache = wb.getPivotCaches().add(dataRange);
PivotTable pt = sheet.getPivotTables()
.add("销售汇总", sheet.getCellRange("G2"), cache);
// 配置透视表
((PivotField)pt.getPivotFields().get("地区")).setAxis(AxisTypes.Row);
((PivotField)pt.getPivotFields().get("产品")).setAxis(AxisTypes.Column);
pt.getDataFields().add(
pt.getPivotFields().get("销售额"),
"总计",
SubtotalTypes.Sum
);
pt.setBuiltInStyle(PivotBuiltInStyles.PivotStyleMedium12);
pt.calculateData();
// 3. 创建三个切片器
XlsSlicerCollection slicers = sheet.getSlicers();
// 地区切片器
int idx1 = slicers.add(pt, "G15", 0);
XlsSlicer regionSlicer = slicers.get(idx1);
regionSlicer.setCaption("地区筛选");
regionSlicer.setStyleType(SlicerStyleType.SlicerStyleLight4);
regionSlicer.setWidth(120);
regionSlicer.isPositionLocked(true);
// 产品切片器
IPivotField productField = pt.getPivotFields().get("产品");
int idx2 = slicers.add(pt, "K15", productField);
XlsSlicer productSlicer = slicers.get(idx2);
productSlicer.setCaption("产品筛选");
productSlicer.setStyleType(SlicerStyleType.SlicerStyleLight5);
productSlicer.setWidth(120);
// 月份切片器
IPivotField monthField = pt.getPivotFields().get("月份");
int idx3 = slicers.add(pt, "O15", monthField);
XlsSlicer monthSlicer = slicers.get(idx3);
monthSlicer.setCaption("月份筛选");
monthSlicer.setStyleType(SlicerStyleType.SlicerStyleLight6);
monthSlicer.setWidth(100);
// 4. 美化工作表
sheet.setName("销售仪表板");
sheet.setDefaultColumnWidth(15);
wb.saveToFile("sales_dashboard.xlsx", ExcelVersion.Version2013);
wb.dispose();
System.out.println("仪表板生成完成!");
System.out.println("打开文件后,点击切片器按钮即可交互式筛选数据。");
}
}这个例子创建了一个完整的销售分析仪表板:
用户可以自由组合筛选条件,比如只看"华东地区的产品A在1月的销售情况",点几下鼠标就能看到结果,无需手动筛选。
isPositionLocked(true) 防止用户误拖动setCaption() 设置易懂的名称切片器不仅可以控制透视表,还能控制图表。如果你的报表里有柱状图、折线图,也可以用切片器来动态切换显示的数据系列。
切片器是个让Excel报表"活起来"的好工具。通过本文的例子,你应该掌握了:
比起传统的自动筛选,切片器的交互体验好太多。如果你的报表需要频繁切换视图、多维度分析,强烈建议加上切片器功能。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。