[{"id":"b66f8b1e-cc14-4e89-9679-abd5687d283d","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"569bb90a-ea68-46c6-96f1-ab151c120714","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"5eb52f08-2d1a-4362-9ffc-4871bdc10f3f","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"341dd607-b97d-4d70-bde2-53acda6b6c95","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"05349273-414f-4208-9ea2-c4fc8f4ea2cb","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"86089f76-b778-4d52-821e-6f27de3df613","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"b81e4fd6-1fc5-43a0-a258-b6e16a5cbec6","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"8aa8ce31-43e4-438e-951f-241608435260","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"37343f41-6ec2-4c7e-b21d-2cc18d5ce1e0","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"5915e52f-64f8-4146-b8bd-81bead6324a3","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"836ba889-af9e-460d-a4cc-c24d922795f2","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"4ae14b06-bb68-4394-a210-a46b8f028346","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"d8f42066-e9dc-4411-bdcf-43b1a203370c","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"7ef86f16-b1a0-49f7-9592-612b9be02b25","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"b29c7775-a9a4-451e-a1b5-01d19ed5ca5e","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"e56f3989-8f81-46af-90fa-a4813eeb976f","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"2526c963-f170-45a8-923e-91b0712a9810","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"24575cf0-501a-44f9-8426-c40f8f4b5552","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"1a6f8d7f-acd6-42be-8c4f-f464c6218381","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"82b176fd-5cab-498c-909e-8fa7d29c38d8","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"1708b3a9-4f37-44a8-8f0e-f9a2d2e5d940","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"c9ac246e-29fb-4bc4-8231-8439795bb590","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"94f2a5c3-2539-436a-af75-23fbbd1a3957","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"d99594f4-2d40-4df4-9419-ba2ca6aa3f7f","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"fd66e72d-0f10-4f57-9807-6db26290ab2e","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"8f344863-503d-4bc3-a594-3815e7d55f5c","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"9be82601-de9d-4c18-948a-23ab6f4dd431","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"6495f3c0-b463-47e0-b08a-ca949672211e","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"b4bede08-3f08-4839-ba4a-abc7ac195bde","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"4afcdfc0-3ff5-4f2b-a223-f8fc042a5bbe","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"422062c4-fa40-4771-a86f-008efe6d86e5","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"d87e8013-86a7-4840-8d25-6f62e14eb4ac","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"a6acedfd-4043-4c64-a5d1-aec3326df9e7","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"dbdc0b24-06c4-48b9-8d6c-7455119dc773","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"a3856849-954a-4cfc-96a6-382e530d3638","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"4a39306b-ffa5-433d-80a3-28e41f929b72","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]}]
        
(Showing Draft Content)

将自动合并效果导出Excel

问题:自动合并的单元格,如何在导出EXCEL文件后仍然合并?


背景:

SpreadJS有一个功能:如果相邻列单元格包含相同的文本并且它们不在任何已合并区域内,则允许相邻单元格自动合并。这个功能优化了用户需要一个一个遍历合并单元格的问题。但是随之带来一个新的问题,即导出excel文件后,发现自动合并的单元格此时被拆分。所以下文将围绕此背景展开解决方案。

解决方案:


我们的SpreadJS支持任何单元格区域的自动合并。如果行和列中的相邻单元格的文本相同并且不在任何合并单元格内容,则它们将自动合并,参考这里的方法,将单元格设置为自动合并

var sheet = spread.getActiveSheet();
var range = new GC.Spread.Sheets.Range(-1, -1, -1, -1);
sheet.autoMerge(range, GC.Spread.Sheets.AutoMerge.AutoMergeDirection.row);

效果如图所示:

image ==========> image

但是如果将上述的内容直接导出成Excel文件,会发现这两个单元格并没有合并

image

该效果只是画法显示层面的合并,实际上单元格之间并没有进行合并。所以在导出的时候并不会按照展示的效果进行单元格合并。在老版本中,如果场景中需要在导出时候也需要有自动合并的效果,AutoMerge是无法满足的,那么就需要我们自己来设计一套自动合并的算法,并利用单元格合并(addSpan)的功能来进行合并。这样可以确保导出Excel时也可以带有合并的效果。

新版本:

SpreadJS新版本已经支持通过选项让导出的文件实现AutoMerge的功能,如下所示:

spread.toJSON({ includeAutoMergedCells: true });

老版本:

首先,我们参考AutoMerge功能的设计分为四种合并方向:按行(byRow),按列(byColumn),先按行再按列(byRowColumn),先按列再按行(byColumnRow)。

接下来,设计自动合并方式的算法,考虑到byRowColumn,byColumnRow这两种组合合并的方式是基于byRow,byColumn的基础上完成的,所以我们需要先设计byRow,byColumn的算法,主要通过循环来进行判断,下面附上算法的逻辑

1. 按照行进行合并
// 按照行合并
function spanbyrow(range){
    var spans = [];
    for(var i=range.row;i<range.rowCount;i++){
        var colCount = 1;var col = 0;
        var startValue = sheet.getValue(i,0);
        for(var j=range.col+1;j<range.colCount;j++){
            var currentValue = sheet.getValue(i,j);
            if(currentValue==startValue){
                colCount++;        
            }else{
                sheet.addSpan(i,col,1,colCount);
                var spanRange = new GC.Spread.Sheets.Range(i,col,1,colCount);
                spans.push(spanRange);
                startValue = currentValue;
                col = j;
                colCount = 1;
            }
            //判断是否到达边界
            if(j == range.col+range.colCount-1){
                sheet.addSpan(i,col,1,colCount);
                var spanRange = new GC.Spread.Sheets.Range(i,col,1,colCount);
                spans.push(spanRange);
            }
        }
    }
    return spans;
}
2. 按照列进行合并
  function spanbycolumn(range){
      var spans = [];
      for(var i=range.col;i<range.col+range.colCount;i++){
          var rowCount = 1;var row = 0;
          var startValue = sheet.getValue(0,i);
          for(var j=range.row+1;j<range.row+range.rowCount;j++){
              var currentValue = sheet.getValue(j,i);
              if(currentValue==startValue){
                   rowCount++;
              }else{
                   sheet.addSpan(row,i,rowCount,1);
                   var spanRange = new GC.Spread.Sheets.Range(row,i,rowCount,1);
                   spans.push(spanRange);
                   startValue = currentValue;
                   row = j;
                   rowCount = 1;
              }
              //判断是否到达边界
              if(j == range.row+range.rowCount-1){
                  sheet.addSpan(row,i,rowCount,1);
                  var spanRange = new GC.Spread.Sheets.Range(row,i,rowCount,1);
                  spans.push(spanRange);
              }
          }
      }
      return spans;
  }
3. 在按照行合并的基础上再按照列进行合并
  function spanbyrowcolumn(range){
      var spans = spanbyrow(range);
      for(var i=0;i<spans.length;i++){
          var row = spans[i].row;
          var col = spans[i].col;
          var rowCount = spans[i].rowCount;
          var colCount = spans[i].colCount;
          var sourceValue = sheet.getValue(spans[i].row,spans[i].col);
          var spanRowCount = rowCount;
          for(var j=spans[i].row+spans[i].rowCount;j<range.row+range.rowCount;j++){
              var spanFlag = true;
              for(var k=spans[i].col;k<spans[i].col+spans[i].colCount;k++){
                  var tempSpan = findSpan(j,k);
                  if(tempSpan && tempSpan.colCount != colCount){
                      spanFlag = false;
                      break;
                  }
                  if(sourceValue!=sheet.getValue(j,k)){
                      spanFlag = false;
                      break;
                  }
              }
              if(spanFlag){
                  spanRowCount++
                  sheet.removeSpan(j,col);
              }else{
                  break;
              }
          }
          if(spanRowCount>1){
              var compareSpan = findSpan(row,col);
              var currentSpan = new GC.Spread.Sheets.Range(row,col,spanRowCount,colCount);
              if(compareSpan !=null){
                  if(!containSpan(currentSpan,compareSpan)){
                      sheet.removeSpan(row,col);
                      sheet.addSpan(row,col,spanRowCount,colCount);
                  }
              }else{
                  sheet.removeSpan(row,col);
                  sheet.addSpan(row,col,spanRowCount,colCount);
              }
          }
      }
}

这里还需要一些对特殊情况的判断,例如在做列合并的时候上下两列如果都是合并单元格的处理方式,边界的判断等

4. 在按照列合并的基础上再按照行进行合并
function spanbycolumnrow(range){
    var spans = spanbycolumn(range);
    for(var i=0;i<spans.length;i++){
        var row = spans[i].row;
        var col = spans[i].col;
        var rowCount = spans[i].rowCount;
        var colCount = spans[i].colCount;
        var sourceValue = sheet.getValue(spans[i].row,spans[i].col);
        var spanColCount = colCount;
        for(var j=spans[i].col+spans[i].colCount;j<range.col+range.colCount;j++){
            var spanFlag = true;
            for(var k=spans[i].row;k<spans[i].row+spans[i].rowCount;k++){
                var currentValue = sheet.getValue(k,j);
                if(sourceValue!=sheet.getValue(k,j)){
                    spanFlag = false;
                    break;
                }
            }
            if(spanFlag){
                spanColCount++
                sheet.removeSpan(row,j);
            }else{
                break;
            }
        }

以上就是4种合并方式的讲解,具体可以参考这两篇技术博客

如何在导出Excel时带有自动合并(AutoMerge)效果(一)

如何在导出Excel时带有自动合并(AutoMerge)效果(二)

作者: Clark.Pan | 审核:Clark.Pan | 更新时间:2023.09.27