議:如何將樹形菜單形式的數據轉化成HTML的二維表(相同內容需合併單元格)

来源:http://www.cnblogs.com/wyfblog/archive/2016/03/25/5319873.html
-Advertisement-
Play Games

一般做OA類管理系統,經常涉及到“組織架構”的概念,那麼像這種有上下層級關係的數據一般會做成樹形菜單的方式顯示,底層代碼必定會用到遞歸演算法。這篇隨筆的目的就是要談談除了用樹形菜單來顯示這種上下層級關係的數據,還有其他的顯示方式嗎?答案是有的,例如即將要談到的二維表顯示方式,同時也是本隨筆的核心內容。 ...


  一般做OA類管理系統,經常涉及到“組織架構”的概念,那麼像這種有上下層級關係的數據一般會做成樹形菜單的方式顯示,底層代碼必定會用到遞歸演算法。這篇隨筆的目的就是要談談除了用樹形菜單來顯示這種上下層級關係的數據,還有其他的顯示方式嗎?答案是有的,例如即將要談到的二維表顯示方式,同時也是本隨筆的核心內容。

  首先來看二維表的顯示效果圖:

如果看到這裡,你覺得這就是你想要的顯示效果,或者對此比較感興趣。請接著往下看的實現步驟:

1.取出所有的數據臨時保存到DataTable中,即記憶體中,拼html時直接查DataTable中的數據,不用去反覆讀取資料庫,提高效率;

2.根據節點編號獲取該節點下所有的末端子節點編號,因為末端子節點的個數就決定了<table>的行數;

3.將查到的末端子節點編號的所有父節點編號也查出來,拼接起來,就知道了<table>的每行的列數;

4.對節點的編號進行排序,這樣可以把每列下的相同行的節點編號集中在一起,方便後面的合併單元格;

5.遍歷行和列,合併每列相同行的單元格;

6.最後一步,拼接空白的列。

如下是具體代碼實現過程:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.Data;
  6 using System.Text;
  7 
  8 /// <summary>
  9 ///KpiTable 的摘要說明
 10 /// </summary>
 11 public class KpiTable
 12 {
 13     DBUtility.SQLHelper sqlhelper = new DBUtility.SQLHelper();
 14     public string GetKpiTable(string kpino, string businessno, string tenderno)
 15     {
 16         //1.取出所有的數據臨時保存到dt2,即記憶體中,拼html時直接查dt2中的數據,不用去反覆讀取資料庫,提高效率
 17         DataTable dt2 = new DataTable();
 18         {
 19             DataSet ds = new DataSet();
 20             int i = sqlhelper.RunSQL(string.Format("select count(1) from sys.objects where name = 'KpiValue{0}'", businessno));
 21             if (string.IsNullOrEmpty(tenderno) || i<1)//如果有標段編號就要把KpiValueXXX表裡的KpiValue1查出來顯示
 22             {
 23                 sqlhelper.RunSQL(string.Format(@"select KpiNo,KpiName,KpiInfo,ISNULL(KpiParentNo,0) KpiParentNo,KpiWeight,0 KpiValue1,'' KpiMethod,'' KpiSampleType,'' KpiRule,'' KpiCriterion,'' KpiAreaRule,'' KpiSampleRule from KpiTree{0}
 24 union all select KpiNo,KpiName,KpiInfo,ISNULL(KpiParentNo,0) KpiParentNo,KpiWeight,0 KpiValue1,KpiMethod,KpiSampleType,KpiRule,KpiCriterion,KpiAreaRule,KpiSampleRule from Kpi{0}",businessno), ref ds);
 25             }
 26             else
 27             {
 28                 sqlhelper.RunSQL(string.Format(@"select * from (
 29 select KpiNo,KpiName,KpiInfo,ISNULL(KpiParentNo,0) KpiParentNo,KpiWeight,0 KpiValue1,'' KpiMethod,'' KpiSampleType,'' KpiRule,'' KpiCriterion,'' KpiAreaRule,'' KpiSampleRule from KpiTree{0}
 30 union all select KpiNo,KpiName,KpiInfo,ISNULL(KpiParentNo,0) KpiParentNo,KpiWeight,0 KpiValue1,KpiMethod,KpiSampleType,KpiRule,KpiCriterion,KpiAreaRule,KpiSampleRule from Kpi{0}
 31 ) a left join KpiValue{0} b on a.kpino = b.kpino and TenderNo='{1}'", businessno, tenderno), ref ds);
 32             }
 33             dt2 = ds.Tables[0];
 34         }
 35         //2.根據節點編號獲取該節點下所有的末端子節點編號,因為末端子節點的個數就決定了table的行數
 36         DataTable dt = new DataTable();
 37         {
 38             DataSet ds = new DataSet();
 39             if (string.IsNullOrEmpty(kpino) || kpino == "0")
 40             {
 41                 sqlhelper.RunSQL(string.Format(@"select kpino from (select kpino from kpitree{0} union all select kpino from Kpi{0}) t where kpino not in (select isnull(KpiParentNo,0) from (select KpiParentNo from kpitree{0} union all select KpiParentNo from Kpi{0}) t)", businessno), ref ds);
 42             }
 43             else
 44             {
 45                 string endKpiNo = RecursionEndKpiNo(dt2, kpino).Trim(',');
 46                 endKpiNo = endKpiNo == "" ? "0" : endKpiNo;
 47                 string kpinos = string.Empty;
 48                 foreach (string str in endKpiNo.Split(',')) { kpinos += "'" + str + "',"; }
 49                 kpinos = kpinos.Trim(',');
 50                 sqlhelper.RunSQL(string.Format(@"select kpino from (select kpino from kpitree{0} union all select kpino from Kpi{0}) t where kpino not in (select isnull(KpiParentNo,0) from (select KpiParentNo from kpitree{0} union all select KpiParentNo from Kpi{0}) t) and kpino in ({1})", businessno, kpinos), ref ds);
 51             }
 52             dt = ds.Tables[0];
 53         }
 54         //3.將查到的末端子節點編號的所有父節點編號也查出來,拼接起來,就知道了table的每行的列數
 55         foreach (DataRow row in dt.Rows)
 56         {
 57             row["kpino"] = Recursion(dt2, row["kpino"]);
 58         }
 59         //4.對編號進行排序,這樣可以把每列下的相同行的節點編號集中在一起,方便後面的合併單元格
 60         var drArray = dt.Select("1=1", "kpino");
 61         //5.限制輸出kpino之前的父節點信息
 62         foreach (DataRow row in drArray)
 63         {
 64             int index = row["kpino"].ToString().IndexOf(kpino);
 65             if (index > -1)
 66             {
 67                 row["kpino"] = row["kpino"].ToString().Substring(index);
 68             }
 69         }
 70         //6.遍歷行和列
 71         int maxCount = GetMaxCount(drArray);
 72         StringBuilder sbJson = new StringBuilder();
 73         for (int i = 0; i < drArray.Length; i++)
 74         {
 75             DataRow row = drArray[i];
 76             sbJson.Append("<tr>");
 77             var kpinoArray = row["kpino"].ToString().Trim(',').Split(',');
 78             int kpinoArrayLenth = kpinoArray.Length;
 79             for (int j = 0; j < kpinoArrayLenth; j++)
 80             {
 81                 string str = kpinoArray[j];
 82                 if (str != "0")
 83                 {
 84                     var dr = dt2.Select("kpino='" + str + "'");
 85                     //合併每列相同行的單元格
 86                     if (dr.Length > 0 && !EqualUpColumnValue(i, j, drArray))
 87                     {
 88                         double kpiWeight = GetKpiWeight(dt2, str);
 89                         double kpiValue = GetKpiValue(dt2, str);
 90                         string kpiValueStr = string.IsNullOrEmpty(tenderno) ? "" : "[" + (kpiValue * kpiWeight).ToString("0.00") + "]";
 91                         string kpiDes = GetKpiDes(dt2, str);
 92                         sbJson.Append(string.Format("<td rowspan='{0}'>{1}({2}%){3}{4}</td>", GetColspan(i, j, drArray), dr[0]["kpiname"], (kpiWeight * 100).ToString("0.00"), kpiValueStr, kpiDes));
 93                     }
 94                 }
 95             }
 96             //拼接空白的列
 97             for (int j = 0; j < maxCount - kpinoArrayLenth; j++)
 98             {
 99                 sbJson.Append("<td></td>");
100             }
101             sbJson.Append("</tr>");
102         }
103         return "<table id='kpitable' border='1px'>" + sbJson.ToString() + "</table>";
104     }
105 
106     private string RecursionEndKpiNo(DataTable dt, object parentId)
107     {
108         StringBuilder sbJson = new StringBuilder();
109 
110         DataRow[] rows = dt.Select(string.Format("KpiParentNo = '" + parentId + "'"));
111         if (rows.Length > 0)
112         {
113             foreach (DataRow row in rows)
114             {
115                 string str = RecursionEndKpiNo(dt, row["kpino"]);
116                 sbJson.Append("" + row["kpino"] + "," + str);
117             }
118         }
119         return sbJson.ToString();
120     }
121     private bool IsChild(DataTable dt, string parentId)
122     {
123         DataRow[] rows = dt.Select(string.Format("KpiParentNo = '" + parentId + "'"));
124         if (rows.Length > 0)
125         {
126             return true;
127         }
128         else
129         {
130             return false;
131         }
132     }
133 
134     private string Recursion(DataTable dt, object parentId)
135     {
136         StringBuilder sbJson = new StringBuilder();
137 
138         DataRow[] rows = dt.Select("kpino = '" + parentId + "'");
139         if (rows.Length > 0)
140         {
141             if (rows[0]["KpiParentNo"].ToString() == "0" || rows[0]["KpiParentNo"].ToString() == "")
142             {
143                 sbJson.Append("0,");
144             }
145             else
146             {
147                 sbJson.Append(Recursion(dt, rows[0]["KpiParentNo"]));
148             }
149         }
150         sbJson.Append(parentId.ToString() + ",");
151         return sbJson.ToString();
152     }
153     private int GetMaxCount(DataRow[] drArray)
154     {
155         int temp = 0;
156         foreach (DataRow row in drArray)
157         {
158             int count = row["kpino"].ToString().Trim(',').Split(',').Length;
159             if (count > temp)
160             {
161                 temp = count;
162             }
163         }
164         return temp;
165     }
166     private bool EqualUpColumnValue(int rowIndex, int colIndex, DataRow[] drArray)
167     {
168         if (rowIndex == 0)
169         {
170             return false;
171         }
172 
173         string[] kpinoArray = drArray[rowIndex - 1]["kpino"].ToString().Trim(',').Split(',');
174         if (kpinoArray.Length > colIndex)
175         {
176             string upColumnValue = drArray[rowIndex]["kpino"].ToString().Trim(',').Split(',')[colIndex];
177             if (upColumnValue == kpinoArray[colIndex])
178             {
179                 return true;
180             }
181             else
182             {
183                 return false;
184             }
185         }
186         else
187         {
188             return false;
189         }
190     }
191     private int GetColspan(int rowIndex, int colIndex, DataRow[] drArray)
192     {
193         int colspan = 1;
194         string[] kpinoArray = drArray[rowIndex]["kpino"].ToString().Trim(',').Split(',');
195 
196         while (rowIndex < drArray.Length - 1)
197         {
198             string[] kpinoArray2 = drArray[rowIndex + 1]["kpino"].ToString().Trim(',').Split(',');
199             if (kpinoArray2.Length > colIndex)
200             {
201                 if (kpinoArray[colIndex] == kpinoArray2[colIndex])
202                 {
203                     colspan++;
204                 }
205                 else
206                 {
207                     break;
208                 }
209             }
210             else
211             {
212                 break;
213             }
214             rowIndex++;
215         }
216         return colspan;
217     }
218     private double GetKpiWeight(DataTable dt, string kpino)
219     {
220         double kpiWeight = 0;
221         var drArray = dt.Select("kpino='" + kpino + "'");
222         if (drArray.Length > 0)
223         {
224             string kpiParentNo = drArray[0]["KpiParentNo"].ToString();
225             double kpino_KpiWeight = Convert.ToDouble(drArray[0]["KpiWeight"]);
226             drArray = dt.Select("KpiParentNo='" + kpiParentNo + "'");
227             if (drArray.Length > 0)
228             {
229                 double result = 0;
230                 foreach (DataRow row in drArray)
231                 {
232                     result += Convert.ToDouble(row["KpiWeight"]);
233                 }
234                 kpiWeight = (kpino_KpiWeight / result);
235             }
236         }
237         return kpiWeight;
238     }
239     private double GetKpiValue(DataTable dt, string kpino)
240     {
241         var drArray = dt.Select(string.Format("kpino='{0}'",kpino));
242         if (drArray.Length>0)
243         {
244             return Convert.ToDouble(drArray[0]["KpiValue1"]);
245         }
246         return 0;
247     }
248     private string GetKpiDes(DataTable dt, string kpino)
249     {
250         string des = string.Empty;
251         var drArray = dt.Select(string.Format("kpino='{0}'",kpino));
252         if (drArray.Length>0)
253         {
254             string KpiMethod = drArray[0]["KpiMethod"].ToString();
255             string KpiSampleType = drArray[0]["KpiSampleType"].ToString();
256             string KpiRule = drArray[0]["KpiRule"].ToString();
257             string KpiCriterion = drArray[0]["KpiCriterion"].ToString();
258             string KpiAreaRule = drArray[0]["KpiAreaRule"].ToString();
259             string KpiSampleRule = drArray[0]["KpiSampleRule"].ToString();
260 
261             //表格樣式
262             if (!string.IsNullOrEmpty(KpiMethod))
263             {
264                 //des += "<table id='kpitabledes'>";
265                 //des += "<tr><td>計算方法:</td><td>" + KpiMethod     +"</td></tr>";
266                 //des += "<tr><td>採樣類別:</td><td>" + KpiSampleType + "</td></tr>";
267                 //des += "<tr><td>評價標準:</td><td>" + KpiRule + "</td></tr>";
268                 //des += "<tr><td>規範要點:</td><td>" + KpiCriterion + "</td></tr>";
269                 //des += "<tr><td>測區規則:</td><td>" + KpiAreaRule + "</td></tr>";
270                 //des += "<tr><td>測點規則:</td><td>" + KpiSampleRule + "</td></tr>";
271                 //des += "</table>";
272             }
273                                      
274             //換行樣式               
275             //if (!string.IsNullOrEmpty(KpiMethod)) { des += "<br />計算方法:" + KpiMethod; }
276             //if (!string.IsNullOrEmpty(KpiSampleType)) { des += "<br />採樣類別:" + KpiSampleType; }
277             //if (!string.IsNullOrEmpty(KpiRule)) { des += "<br />評價標準:" + KpiRule; }
278             //if (!string.IsNullOrEmpty(KpiCriterion)) { des += "<br />規範要點:" + KpiCriterion; }
279             //if (!string.IsNullOrEmpty(KpiAreaRule)) { des += "<br />測區規則:" + KpiAreaRule; }
280             //if (!string.IsNullOrEmpty(KpiSampleRule)) { des += "<br />測點規則:" + KpiSampleRule; } 
281         }
282         return des;
283     }
284 
285 
286 
287     
288 }
View Code

以及需要用到的表(sql腳本):

  1 USE [Evaluation]
  2 GO
  3 /****** Object:  Table [dbo].[Kpi]    Script Date: 2016/3/25 16:06:04 ******/
  4 SET ANSI_NULLS ON
  5 GO
  6 SET QUOTED_IDENTIFIER ON
  7 GO
  8 CREATE TABLE [dbo].[Kpi](
  9     [KpiNo] [nvarchar](50) NOT NULL,
 10     [KpiName] [nvarchar](50) NULL,
 11     [KpiInfo] [nvarchar](100) NULL,
 12     [KpiParentNo] [nvarchar](50) NULL,
 13     [KpiMethod] [nvarchar](50) NULL,
 14     [KpiWeight] [decimal](18, 2) NULL,
 15     [KpiRule] [nvarchar](100) NULL,
 16     [KpiCriterion] [nvarchar](100) NULL,
 17     [KpiAreaRule] [nvarchar](100) NULL,
 18     [KpiSampleRule] [nvarchar](100) NULL,
 19     [KpiAreaNum] [int] NOT NULL,
 20     [KpiSampleNum] [int] NOT NULL,
 21     [KpiMinValue] [decimal](18, 2) NULL,
 22     [KpiMaxValue] [decimal](18, 2) NULL,
 23     [KpiOffset] [decimal](18, 2) NULL,
 24     [KpiReferenceVal] [decimal](18, 2) NULL,
 25     [KpiValueType] [nvarchar](50) NULL,
 26     [KpiFormula] [nvarchar](50) NULL,
 27     [KpiFormulaRule] [nvarchar](100) NULL,
 28     [KpiMemo] [nvarchar
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 所有目錄務必保持具有X許可權!!,否則無法進入該目錄及子目錄,且無法讀取該目錄及子目錄下的文件或子目錄
  • 最近在Linux平臺上配置伺服器部署網站(說多了都是淚!),記個筆記! 一、首先是在centos下安裝mysql (參考博客) mysql yum庫提供了一個簡單的和方便的方法來安裝和更新MySQL相關的軟體包到最新版本。 參考文檔:http://dev.mysql.com/downloads/re
  • 本文將tomcat安裝到了/alidata/server/目錄下,當然也可以安裝到其他目錄。 1. 下載tomcat:#wget http://apache.fayea.com/tomcat/tomcat-7/v7.0.54/bin/apache-tomcat-7.0.54.tar.gz 2. 將t
  • 2016-03-18 17:10:19 張超《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 我的實驗平臺以及代碼見https://www.shiyanlou.com/courses/reports/986221 實驗
  • 如何查看、備份電腦隱藏的恢復分區 步驟: 1.用管理員身份打開CMD(快捷鍵:1. 同時按 win+x 2. 按 a ),輸入diskpart,回車enter。 (或者 按 win+r 在運行中輸入 diskpart 也行)。 2.輸入 lis dis ,回車。 (lis dis 是 list di
  • 1、安裝全部桌面環境,其實Ubuntu系列桌面實際上有幾種桌面應用程式,包括Ubuntu-desktop、Kubunut-desktop和Xubuntu- desktop。 我們就安裝了Ubuntu-desktop還有Gnome因為安裝桌面相關軟體太多。 命令:#sudo aptitude inst
  • When you try invoke a Java/Axis Web Service from a proxy class generated by Visual Studio 2005 or Visual Studio 2008 you often crash against the ‘retu ...
  • 術語約定文章中會反覆出現[值類型]、[包裝類型]、[普通引用類型]、[元素節點]和[元素取值]的表述1> [值類型]指的是java和.NET中的基本數據類型,如:int;2> [包裝類型]指的是java中的包裝類和.NET中的Nullable<T>類型,如:Integer、int?;3> [普通引用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...