問題描述
輸出報表的項目中有一個需求是把多級菜單輸出到excel中。比如菜單“5”下面包含子菜單“1”和“2”。子菜單下面又有菜單。一共三級。
我們很容易把菜單數據直接輸出,如圖(a)所示。
合併冗餘項之後如圖(b)所示。
具體如何合併菜單呢?
已經有函數可以把給定區域序號之間的單元格合併。合併之後新單元格的值是區域最左上角元素的值。
討論
容易看出只需要合併同一行的相同元素,不用考慮跨列的合併。
問題可以轉換成:給定一個序列以及起止下標,給出該範圍內所有可以合併的子序列起止下標。
三級菜單已經分割完畢,不需要處理。
一級菜單遍歷一遍可以在O(1)的複雜度內給出結果。
假設起止下標爲(left,right),我們用mid指針遍歷這個序列,當mid與left所指的值不同時就意味着得到一個子序列(left,mid-1)。遍歷結束後可以得到所有結果
爲了方便處理最後一段子序列,mid需要遍歷到right+1位置才能結束。我們可以給right+1列添加一個BORDER值,標記結束。
要注意二級菜單的分割範圍受到了一級菜單的影響,即不能越界:
這樣是錯的。
所以可以利用上一步的結果,得到最終的合併方案。
順便補充一下:
- springboot中使用poi寫excel的方法:https://github.com/shenjiefeng/springboot-examples/tree/master/ex03-excel
- 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));
}
}