Go語言實現excel匯入無限級選單結構
阿新 • • 發佈:2020-11-24
[toc]
# 一、需求
最近有一個需求,要實現一個無限級結構的樹型選單,差不多長下面這個樣子
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124162102779-728697141.png)
我們知道無限級實現思路都是用一個parent_id將各種層級串聯起來,頂級的parent_id為0,例如如下層級的選單
```
選單一
選單二
選單三
選單四
選單五
選單六
選單7
選單八
```
在資料庫中的儲存一般是如下形式
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124161952092-310075861.png)
原理就會記錄每一個選單的父級ID(parent_id),通過這樣的父級ID會構造出一棵樹型結構,層級(level)是為了標明當前選單是處於哪個層級
問題來了,一般這樣的結果要是一條一條插入,再人工用parent_id串起來,太反人類了,低效!
產品會讓工程師通過表格匯入這樣的資料,表格差不多都長如下這個樣子
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124162250898-867362899.png)
我們需要用過程式碼來實現生成上面資料庫的結果,talk is cheap, show you the code
# 二、程式碼實現
```
func ImportMenus() (res interface{}, err error) {
columns := 5 //支援的無限級選單數量,想支援多少級寫多少
templateFile := "/Users/chenqionghe/Downloads/menus.xlsx" //匯入的表格路徑
f, err := excelize.OpenFile(templateFile) //讀取表格
if err != nil {
return nil, err
}
rows, err := f.GetRows("Sheet1")
if err != nil {
return nil, err
}
var allRowIds = make([][]int, len(rows)) //初始化儲存ID的陣列,通過下標定位對應選單生成的ID
for i, _ := range rows {
allRowIds[i] = make([]int, columns)
}
var parentId int
tx := db.DB().Begin()
exception.Block{
Try: func() {
for i, row := range rows {
if i == 0 { //表頭跳過
continue
}
//構造無限級選單
for j := 0; j < columns; j++ {
if row[j] == "" { //空值不操作
continue
}
if j == 0 && row[j] != "" { //頂級按鈕父級ID是0
parentId = 0
}
if j > 0 { //非頂級,向前或向上尋找最近的父級ID
if allRowIds[i][j-1] != 0 {
parentId = allRowIds[i][j-1] //向前找ID作為父級ID
} else {
for z := i - 1; z > 0; z-- {
if allRowIds[z][j-1] != 0 {
parentId = allRowIds[z][j-1] //向上找ID作為父級ID
break
}
}
}
}
newData := &model.Menu{Name: row[j], ParentID: parentId, Level: j + 1}
if err = tx.Save(newData).Error; err != nil { //選單插入資料庫
panic(err)
}
allRowIds[i][j] = newData.ID //儲存當ID到陣列對應陣列下標中,供後續選單作為父級ID使用
}
}
tx.Commit()
err = nil
},
Catch: func(e interface{}) {
tx.Rollback()
err = fmt.Errorf("err: %v", e)
},
}.Do()
return allRowIds, err
}
```
# 三、程式碼測試
先建立對應的資料表,結構如下
```
CREATE TABLE `menu` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '選單ID',
`name` varchar(255) NOT NULL COMMENT '選單名稱',
`parent_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '上級選單ID',
`level` tinyint(1) NOT NULL COMMENT '層級',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='選單表';
```
## 簡單例子
我們來測試一下匯入上面的表格
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124162250898-867362899.png)
執行結果如下
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124164009688-633378056.png)
可以看到,結果和我們設想的資料庫結果完全一樣!
## 複雜例子
好,我們再測試一個更復雜的例子,表格模板如下
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124160539999-252964321.png)
匯入的結果如下
![](https://img2020.cnblogs.com/blog/662544/202011/662544-20201124170409925-221876034.png)
這樣就用Go實現了一個支援無限級選單的表格匯入,以上程式碼由chenqionghe提供,轉載請標明出處