模拟Excel同一列相同值的单元格合并
背景
项目中有一个查询工作量,可以将查询的结果导出到Excel表中。在Excel工具中,有一个合并居中功能,可以将选中的单元格合并成一个大的单元格。现在需要在程序中直接实现查询结果的汇总,
问题分析
话不多说,上图分析:
如图,对于第一列,前三行的值都为A,那么就是需要执行合并。与此同时,1-3行后面的列采取同样的措施,约定前6列(下标0-5)。
手动对1-3列进行分析的结果,如图,有点花哨!!!
可以看到结果中,对于整个1-3行后继的列操作依然如此。
这里要突出讲一下第3列(值为R),该列全部为
R
,但是,在第二列中,前两行的值一样为F
,第三行的值为D
,这里就说明前两行应该拿在一起看了,而第三行需要单独分割开来,即使后面的列取值相同。
思想
这里的难点是如何确保第一列之后的列能够按照需求进行合并,同时像上面分析中提出的第三列,虽然取值相同,但是只能合并前两列。
如果只合并第一列中相同的值,那么很简单,确定开始行标,结束行标,执行合并即可。对于第一列,最开始的下标是0,最后的下标是整个表的行数-1,这是遍历范围。
其实发散来看,后面的操作和第一列一样,不同在于确定开始和结束的下标,以及范围。
- 对于第2列,范围就是第一列确定的范围,是一个值,比如示例中第2行范围为1-3。
- 对于第3列,范围来自第2列,但是要注意,这里大范围仍然是1-3,但是里面却要区分为1-2,和3,其实到这里就可以看出递归的思想了。
实现
代码(利用java二维数组模拟实现):
/**
* @ClassName: Demo
* @Author: fanjiajia
* @Date: 2019/3/2 下午8:14
* @Version: 1.0
* @Description: 模拟Excel表合并操作
*/
public class Demo {
public static void main(String[] args) {
int[][] arr = {
{1,2,3,4,6,6,7,8,3},
{1,2,3,4,6,8,9,8,5},
{1,8,3,4,5,6,7,8,6},
{4,2,3,4,5,6,7,8,7},
{1,2,5,4,5,6,7,8,8},
{1,2,5,4,5,7,7,8,6},
{1,3,3,4,6,6,7,8,8},
{1,3,3,4,5,7,7,8,9},
};
// 1.开始执行合并
executMerge(arr);
// 2.合并结束,打印结果
for(int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[0].length; j++) {
System.out.print(arr[i][j] + ",");
}
System.out.println();
}
}
private static void executMerge(int[][] arr) {
int begainIndex = 0; // 开始行,0行
int endIndex = getEndIndex(0,arr, 0, arr.length); // 查找最开始第一列从1(下标0)行开始值相同的最后一行下标
// 外围控制,第一列的合并
while (begainIndex < arr.length){
mergeContorl2(arr, begainIndex, endIndex, 0); // 递归执行
begainIndex = endIndex + 1; // 第一列下一次执行行开始下标
endIndex = getEndIndex(endIndex + 1, arr, 0, arr.length); // 获取下次结束的下标
}
}
/**
* 递归执行
* @param arr 表
* @param rowbeg 行开始下标
* @param rowend 行结束下标
* @param col 列下标
*/
private static void mergeContorl2(int[][] arr, int rowbeg, int rowend,int col) {
// 1. 执行当前的合并操作
merge(arr, rowbeg, rowend, col);
// 2.执行后面的操作
if (col > 5) { // 只合并前面6列,递归结束条件
return;
}
// 3.执行后面列的操作
for (int i = rowbeg; i <= rowend; i++) {
int begin = i;
int end = getEndIndex(begin, arr, col +1,rowend);
while (begin <= rowend){ // 这里保证后面所有的行都能遍历到
mergeContorl2(arr,begin,end, col +1); // 开启递归
begin = end +1;
end = getEndIndex(begin, arr, col + 1, rowend);
}
}
}
/**
* 执行合并操作
* @param arr 表
* @param begin 开始行下标
* @param end 结束行下标
* @param col 列
*/
private static void merge(int[][] arr,int begin, int end, int col){
for(int row = begin; row <= end; row++) {
arr[row][col] = row == begin? arr[begin][col] : 0;
}
}
/**
* 获取同一列相同的值的最后(行)下标
* @param i 当前行下标
* @param arr 表
* @param j 列
* @param endIndex 约束最多遍历至第几行
* @return
*/
private static int getEndIndex(int i, int[][] arr, int j, int endIndex) {
if (i >= endIndex || i >= (arr.length -1)){ //
return i;
}
if (arr[i][j] == arr[i+1][j]){
return getEndIndex(i+1, arr, j,endIndex); // 开启递归
}else {
return i;
}
}
}
结果
- 输入
{1,2,3,4,6,6,7,8,3},
{1,2,3,4,6,8,9,8,5},
{1,8,3,4,5,6,7,8,6},
{4,2,3,4,5,6,7,8,7},
{1,2,5,4,5,6,7,8,8},
{1,2,5,4,5,7,7,8,6},
{1,3,3,4,6,6,7,8,8},
{1,3,3,4,5,7,7,8,9},
- 输出
1,2,3,4,6,6,7,8,3,
0,0,0,0,0,8,9,8,5,
0,8,3,4,5,6,7,8,6,
4,2,3,4,5,6,7,8,7,
1,2,5,4,5,6,7,8,8,
0,0,0,0,0,7,7,8,6,
0,3,3,4,6,6,7,8,8,
0,0,0,0,5,7,7,8,9,
说明,合并操作用0表示,比如第一列1,下面2个0,表示这三行执行合并,值为1.
最后
此致,敬礼
模拟Excel同一列相同值的单元格合并的更多相关文章
- EXCEL在改动某几个单元格时隐藏空列
概述 今天我哥来找我帮他搞下excel表格,本着程序猿对程序无所不能的精神,我爽快的答应了.结果查了半天才搞定.现在记录在此,供自己以后参考,相信对其他人也有用. PS:这几天正在弄博客,马上就要弄完 ...
- excel中在某一列上的所有单元格的前后增加
excel中在某一列上的所有单元格的前后增加数字汉字字符等东西的函数这样写 “东西”&哪一列&“东西” 例如 “1111”&E1&“3333”
- 【原创】.NET读写Excel工具Spire.Xls使用(3)单元格控制
本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...
- java POI excel 导出复合样式(一个单元格两个字体)
前言:java poi 导出 excel 时,需要设置一个单元格有多个字体样式,有点类似于富文本. 想要达到的效果(一个单元格里): 我使用的 poi 版本是 <dependency> & ...
- NPOI 生成Excel (单元格合并、设置单元格样式:字段,颜色、设置单元格为下拉框并限制输入值、设置单元格只能输入数字等)
NPIO源码地址:https://github.com/tonyqus/npoi NPIO使用参考:源码中的 NPOITest项目 下面代码包括: 1.包含多个Sheet的Excel 2.单元格合并 ...
- POI实现EXCEL单元格合并及边框样式
POI实现EXCEL单元格合并及边框样式 下面例子为创建产生一个excel,合并单元格,然后为合并后的单元格添加边框 package test; import java.io.FileOutp ...
- Excel VBA入门(八)单元格边框
本文基于以下文件 http://pan.baidu.com/s/1nvJtsu9 (部分)内容预览: 1. 边框样式 Sub cell_format() Dim sht As Worksheet Di ...
- excel技巧--单元格合并与拆分
如果要将上图的地区列做成下图的合并单一列: 有如下做法: (以下图表格为例) 1.选择要排序的表格,点击“开始”-->排序和筛选-->自定义排序.在对话框选择“业务项目”进行排序: 2.选 ...
- Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等
目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 ...
随机推荐
- js新开窗口避免浏览器拦截解决方案
Ajax回调函数中,打开新窗口解决方案 var w = window.open(); $.post("GetHomToTestPaper", {homeworkName:homew ...
- JS 创建对象总结
狭义:new 构造函数. (注:在JS中创建对象只有一种方式,就是new 构造函数.其中字面量的方式是一种语法糖,本质仍然是new 构造函数) 广义:工厂模式(解决复杂度) 构造函数模式(解决复杂度, ...
- vim ,vi总是卡死,终于找到原因了。
玩了这么多年linux 居然不知道这个..特此记录. 使用vim时,如果你不小心按了 Ctrl + s后,你会发现不能输入任何东西了,像死掉了一般,其实vim并没有死掉,这时vim只是停止向终端输出而 ...
- 『Python基础-5』数字,运算,转换
『Python基础-5』数字,运算,转换 目录 基本的数字类型 二进制,八进制,十六进制 数字类型间的转换 数字运算 1. 数字类型 Python 数字数据类型用于存储数学上的值,比如整数.浮点数.复 ...
- php7+apache2.4+mysql 环境配置(window环境)
最近,小主从事PHP开发.特将最近如何搭建php7的过程记录在此!希望有需要,可以借鉴!( 电脑必须win7 sp1以上, .netframework4 ) Windows7安装php7,Win7+p ...
- java 获取目标时间到当前时间中间的月份和每月最大时间
话不多说自己上代码: Date firstDate = DateUtil.formate("2018-01-01", "yyyy-MM-dd"); Date c ...
- 【8086汇编-Day6】关于loop的实验
实验内容 因为是要复制代码,所以常规来做是取代码段地址来用,所以把cs值mov给ax,但是这只是临时的,ax之后还有别的用途,那就把指令当作数据来存(把ax值 mov给ds,表示这一段地址用作代码段, ...
- DevExpress 操作gridcontrol
XtraGrid的关键类就是:GridControl和GridView.GridControl本身不显示数据,数据都是显示在GridView/CardView/XXXXView中.GridContro ...
- ORB-SLAM(五)KeyFrame类-最小生成树
KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量).对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理 ...
- 封装Excls数据导出功能 返回一个下载链接地址
/// <summary> /// 获取本地存储地址 /// </summary> /// <param name="dt"></para ...