合併單元格

問題描述

輸出報表的項目中有一個需求是把多級菜單輸出到excel中。比如菜單“5”下面包含子菜單“1”和“2”。子菜單下面又有菜單。一共三級。

我們很容易把菜單數據直接輸出,如圖(a)所示。
合併冗餘項之後如圖(b)所示。

具體如何合併菜單呢?

已經有函數可以把給定區域序號之間的單元格合併。合併之後新單元格的值是區域最左上角元素的值。

討論

容易看出只需要合併同一行的相同元素,不用考慮跨列的合併。

問題可以轉換成:給定一個序列以及起止下標,給出該範圍內所有可以合併的子序列起止下標。

三級菜單已經分割完畢,不需要處理。
一級菜單遍歷一遍可以在O(1)的複雜度內給出結果。
假設起止下標爲(left,right),我們用mid指針遍歷這個序列,當mid與left所指的值不同時就意味着得到一個子序列(left,mid-1)。遍歷結束後可以得到所有結果


爲了方便處理最後一段子序列,mid需要遍歷到right+1位置才能結束。我們可以給right+1列添加一個BORDER值,標記結束。

要注意二級菜單的分割範圍受到了一級菜單的影響,即不能越界:


這樣是錯的。

所以可以利用上一步的結果,得到最終的合併方案。

順便補充一下:

  1. springboot中使用poi寫excel的方法:https://github.com/shenjiefeng/springboot-examples/tree/master/ex03-excel
  2. poi中設置單元格顏色:http://blog.csdn.net/downkang/article/details/14164811

實現

import javafx.util.Pair;

import java.util.ArrayList;
import java.util.Arrays;

public class Main {

    private static ArrayList<Pair<Integer, Integer>> GetSpan(ArrayList<String> line,
                                                             ArrayList<Pair<Integer, Integer>> borders) {
        ArrayList<Pair<Integer, Integer>> res = new ArrayList<>();

        for (Pair<Integer, Integer> p : borders) {
            Integer left = p.getKey();
            Integer right = p.getValue() + 1;
            for (int mid = left; mid <= right; mid++) {
                if (!line.get(mid).equals(line.get(left))) {
                    if (mid - 1 > left) {
                        res.add(new Pair<>(left, mid - 1));
                    }
                    left = mid;
                }
            }
            if (left.equals(p.getKey())) {
                res.add(new Pair<>(left, right - 1));
            }
        }
        return res;
    }

    public static void main(String[] args) {

//        String[] t={"0","1","2","3","5","5","6","6","7","7","|"}; // eg1
        String[] t = {"0", "1", "2", "3", "1", "1", "1", "1", "1", "1", "|"}; // eg2
        ArrayList<String> line = new ArrayList<String>(Arrays.asList(t));
//        System.out.println(line);

        ArrayList<Pair<Integer, Integer>> border = new ArrayList<>();
//        border.add(new Pair<Integer, Integer>(4,9)); // eg1
        border.add(new Pair<>(4, 5)); // eg2
        border.add(new Pair<>(6, 7));
        border.add(new Pair<>(8, 9));

        System.out.println(GetSpan(line, border));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章