1. 程式人生 > >Go語言實現excel匯入無限級選單結構

Go語言實現excel匯入無限級選單結構

[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提供,轉載請標明出處