模拟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二维数组模拟实现):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    /**
    * @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
    5
    6
    7
    8
    {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
    5
    6
    7
    8
    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.

最后

此致,敬礼

~~客官随意,我只是学习怎么配置打赏而已~~