上次摸懂動態Class後~
https://ithelp.ithome.com.tw/questions/10215682
我在想有沒有更簡單的動態欄位匯出~
後來想到以前寫ASP、PHP的模擬資料庫介面寫法
也就是根據資料庫帶出底下的資料表,
再根據資料表帶出欄位的名稱、屬性、預設值等...
果然在MVC版本其實也是可以迴圈動態抓資料表的欄位名 (LinQ 沒辦法)
那就更簡單了~只要一個公版Excel匯出功能頁
其他功能頁的匯出功能~直接套用此頁匯出就好
我的寫法如下,在資料庫新增 自訂函數、預存程序(各種匯出欄位的輸出)
首先在資料庫新增 自訂函數 Split 切割字串用
create function dbo.Set_Split(
@Parameter nvarchar(max)
,@Index int
)
Returns nvarchar(max)
as
begin
-- 或可用 String_Split 但要2016版本以上才可以使用
declare @i int = 0
declare @Char_Start int = 1
declare @Char_End int = 1
declare @Char_Length int = 0
declare @Length int = len(@Parameter)
declare @Count int = @Length - len(Replace(@Parameter,',',''))
declare @Str nvarchar(max)
while(@i <= @Count)
begin
set @Char_End = CharIndex(',',@Parameter,@Char_Start)
if(@i=@Count)
begin
set @Char_End = @Length + 1
end
set @Char_Length = @Char_End - @Char_Start
if(@Index=@i)
begin
set @Str = SubString(@Parameter,@Char_Start,@Char_Length)
end
if(@Str='')
begin
set @Str = null
end
set @Char_Start = @Char_End + 1
set @i = @i + 1
end
Return @Str
end
然後自訂要匯出的預存程序
create procedure Excel_Students
@Parameter nvarchar(max) = null
as
begin
--自訂匯出的預存程序 學生資料表
--搜索條件
declare @Id nvarchar(10) = dbo.Set_Split(@Parameter,0)
declare @Name nvarchar(10) = dbo.Set_Split(@Parameter,1)
declare @Sex nvarchar(10) = dbo.Set_Split(@Parameter,2)
--要匯出的資料表
select Id 學生編號
,Name 姓名
,Sex 性別
from Students
where 1=1
and (@Id is null or @Id = Id)
and (@Name is null or Name like N'%' + @Name + '%')
and (@Sex is null or @Sex = Sex)
end
最後是公版的Excel匯出頁
using System.Web.Mvc;
using System.IO;
using WebMvcEF.Models;
using NPOI.HSSF.UserModel;
//測試區 2024-05-25 By Jerwei
namespace WebMvcEF.Controllers.RPT
{
public class ExcelController : Controller
{
/// <summary>
/// 進入匯出Excel
/// </summary>
/// <returns></returns>
public ActionResult ReportSet(string ProcedureName,string Parameters = "", string FileName= "資料")
{
//建立Excel空白檔案
var hssfworkbook = new HSSFWorkbook(); //建立活頁簿
var sheet = hssfworkbook.CreateSheet("sheet"); //建立sheet
//設定樣式
//var headerStyle = hssfworkbook.CreateCellStyle();
//var headerfont = hssfworkbook.CreateFont();
//headerStyle.Alignment = HorizontalAlignment.Center; //水平置中
//headerStyle.VerticalAlignment = VerticalAlignment.Center; //垂直置中
//headerfont.FontName = "微軟正黑體";
//headerfont.FontHeightInPoints = 20;
//headerfont.Boldweight = (short)FontBoldWeight.Bold;
//headerStyle.SetFont(headerfont);
//新增標題列
//sheet.CreateRow(0); //需先用CreateRow建立,才可通過GetRow取得該欄位
//sheet.AddMergedRegion(new CellRangeAddress(0, 1, 0, 2)); //合併1~2列及A~C欄儲存格
//sheet.GetRow(0).CreateCell(0).SetCellValue("測試");
//sheet.GetRow(0).GetCell(0).CellStyle = headerStyle; //套用樣式
// CreateRow(2) 建立第3列
// GetRow(2) 取得第3列位置
// CreateCell(0) 建立第0欄
// SetCellValue("學生姓名") 填入資料
var Sql = @"
if(OBJECT_ID('" + ProcedureName.Replace("'","") + @"','P')) is not null
begin
exec " + ProcedureName.Replace("'","") + @" '" + Parameters.Replace("'", "''") + @"'
end
else
begin
select N'找不到預存程序!' '異常錯誤!'
end
";
var dt = MSSQLHelper.GetTable(Sql, System.Data.CommandType.Text);
//寫入欄位名稱
var rowIndex = 0;
for (var i = 0; i < dt.Columns.Count ; i++)
{
if (i == 0)
{
sheet.CreateRow(rowIndex).CreateCell(i).SetCellValue(dt.Columns[i].ToString());
}
else
{
sheet.GetRow(rowIndex).CreateCell(i).SetCellValue(dt.Columns[i].ToString());
}
}
foreach (System.Data.DataRow dr in dt.Rows)
{
//寫入欄位資料
rowIndex++;
for (var i = 0; i < dt.Columns.Count; i++)
{
if (i == 0)
{
sheet.CreateRow(rowIndex).CreateCell(i).SetCellValue(dr[i].ToString());
}
else
{
sheet.GetRow(rowIndex).CreateCell(i).SetCellValue(dr[i].ToString());
}
}
}
var excelDatas = new MemoryStream(); //建立IO檔案資料流
hssfworkbook.Write(excelDatas); //將Excel資料寫入資料流
return File(excelDatas.ToArray(), "application/vnd.ms-excel", string.Format(FileName + $".xls"));
}
}
}
假如是要將DB的資料匯出成excel可以試試看Dapper+MiniExcel,以下程式碼為.Net Core的主控台應用程式
using Dapper;
using System.Data.SqlClient;
using MiniExcelLibs;
using var connection = new SqlConnection("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=IThomeSample;");
var result = await connection.QueryAsync("SELECT * FROM Students");
MiniExcel.SaveAs("Students.xlsx", result);
我發現這是更有效的方法之一,允許多個匯出函數重複使用單一 Excel 匯出表 geometry dash deadlocked 從而提高程式碼的可重複使用性和更好的可維護性。