模拟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.

最后

此致,敬礼

原文地址:https://www.cnblogs.com/numen-fan/p/10472936.html

时间: 2024-11-04 01:50:42

模拟Excel同一列相同值的单元格合并的相关文章

EXCEL在改动某几个单元格时隐藏空列

概述 今天我哥来找我帮他搞下excel表格,本着程序猿对程序无所不能的精神,我爽快的答应了.结果查了半天才搞定.现在记录在此,供自己以后参考,相信对其他人也有用. PS:这几天正在弄博客,马上就要弄完啦,弄完就把这些手记搬到博客上面啦! 说明 EXCEL的条件格式不能改变单元格的高宽,不能删掉单元格,不能隐藏单元格. 要实现这些功能需要用VBA编写宏,其中用到了EXCEL的Change事件. EXCEL的Change事件是当改变单元格时自动运行的,不需要绑定按钮. 用法 右键点击工作表的标签,然

NPOI 生成Excel (单元格合并、设置单元格样式:字段,颜色、设置单元格为下拉框并限制输入值、设置单元格只能输入数字等)

NPIO源码地址:https://github.com/tonyqus/npoi NPIO使用参考:源码中的 NPOITest项目 下面代码包括: 1.包含多个Sheet的Excel 2.单元格合并 3.设置单元格样式:字段,颜色 4.设置单元格为下拉框并限制输入值 5.设置单元格只能输入数字 // // GET: /Excel/ public ActionResult Write() { var workbook = new HSSFWorkbook();//从流内容创建Workbook对象

java POI excel 导出复合样式(一个单元格两个字体)

前言:java poi 导出 excel 时,需要设置一个单元格有多个字体样式,有点类似于富文本. 想要达到的效果(一个单元格里): 我使用的 poi 版本是 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> 具体实现: 工具类方法:

【web开发】☆★之利用POI操作Excel表格系列教程【11】单元格合并

[web开发]☆★之利用POI操作Excel表格系列教程[11]单元格合并 package csg.xiaoye.poidemo; import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.p

支持将数据导出到Excel文档的时候设置单元格格式的.NET控件Spire.DataExport

Spire.DataExport for .NET是e-iceblue公司推出的一款数据导出类.NET控件.作为一款专业的数据导出控件,Spire.DataExport for .NET可以帮助开发人员轻松快速的从各种主流数据库中导出数据并存储于各种文件格式中.他支持从SQL Command, DataTable,ListView中导出数据并存储于MS Excel,MS Word, HTML, XML, PDF, MS Access, DBF, SQL Script, SYLK, DIF, CS

Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 一.概述 最近在研究QTableView支持多级表头的事情,百度了下网上资料还是挺多的.实现的方式总的来说有2种,效果都还不错,最主要是搞懂其中的原理,做到以不变应万变. 实现多级表头的方式有以下两种方案 行表头和列表头都是用一个表格去模拟 重写QHeadView 以上两种方式都可以实现多级表头,各

SNF快速开发平台MVC-表格单元格合并组件

1.   表格单元格合并组件 1.1.      效果展示 1.1.1.    页面展现表格合并单元格 图 4.1 1.1.2.    导出excel合并单元格 图 4.2 1.2.      调用说明 1.2.1.    表格合并单元格调用说明 首先,要有一个在viewModel中绑定的表格,例如,我们有一个绑定对象为this.grid的表格 我们要在表格的onLoadSuccess事件中添加一个方法 snf.mergeCellsByParentField ("grid", &quo

JTable 单元格合并 【转】

单元格合并 一.单元格合并.(1)我们可以使用Jtable的三个方法:getCellRect(),columnAtPoint(),and rowAtPoint().第一个方法返回一个单元格的边界(Rectangle类),第二.三个方法分别返回屏幕指定位置的列和行.为了实现单元格合并,我们需要重载(overwrite)这三个方法. (2)另外我们需要找出渲染Jtable的ComponentUI对象,并且修改它以达到我们的目的. (3)创建新的类记录单元格合并情况的数据模型,它要包涵一个方法来取得单

FastReport单元格合并

FastReport 自带的单元格合并功能为“抑制重复值”,功能真的很弱,还不如不用.网上也有不少解决方案,不过用来用去,都不尽人意. 下面是网上的两个方案: 1.报表脚本中写代码解决:单元格合并 2.修改相关源代码解决:单元格合并 最初我是两种方案结合使用,第1种方案的缺点是很明显的,有时需要写很多的代码,一不小心容易出错:第2种方案也存在问题,似乎只处理第一页的的情况,当有多页时,就乱套了. 由于本人多个软件都是使用fastreport报表控件,随着时间推移,报表越来越多,设计报表也带来了很