承上次提問,是乎都沒回答
請問如何讓class類別的欄位動態建立?
https://ithelp.ithome.com.tw/questions/10215657
我自己再次Google找答案看看~有無讓class類別的欄位動態建立
經測試將Class屬性定義簡單化,在Excel依舊是一樣的欄位
所以找到這網址教學,再根據開發軟體的智能建議修正程式碼
C#匿名对象(转JSON)互转、动态添加属性
https://www.cnblogs.com/elves/p/6087186.html
成功設置動態class類別的欄位動態建立
但問題出現這個動態類別,不會增加寫第二列的資料
請問各位高手如何修改呢?!
原本寫入Excel問題如下
希望能變成以下結果的畫面
另外附上該頁的測試程式碼
using System.Web.Mvc;
using System.Diagnostics;
using System.Collections.Generic;
using Npoi.Mapper;
using System.IO;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
//測試區 2024-05-12 By Jerwei
namespace WebMvcEF.Controllers.RPT
{
public class WHSalaryRPTforHRController : Controller
{
/// <summary>
/// 頁面載入
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
return View();
}
/// <summary>
/// 進入匯出Excel
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult ReportSet()
{
var Field = new List<string>
{
"學號"
,"學生姓名"
,"性別"
,"縣市"
,"手機"
};
//建置動態Class並建置動態屬性(Excel欄位名稱)
var NewClassObj = DynamicClassHelper.NewClass(Field);
var listclass = new List<dynamic>();
dynamic NewClassModel = NewClassObj.CreateInstance("dynamicclass");
if (NewClassModel != null)
{
//設定值1
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學號", "Test1");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學生姓名", "Test2");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "性別", "Test3");
//設定值2
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學號", "Test4");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學生姓名", "Test5");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "性別", "Test6");
}
listclass.Add(NewClassModel);
var mapper = new Mapper(); //建立Excel操作物件
var stream = new MemoryStream(); //建立IO檔案資料流
//將listclass陣列生成的Excel資料,直接放置到Stream資料流
mapper.Save(stream, listclass, "sheet1", overwrite: true, xlsx: true);
//下載Excel檔案
return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Student.xlsx");
}
}
//使用動態Class功能
public class DynamicClassHelper
{
/// <summary>
/// 建置動態Class並建置動態屬性
/// </summary>
/// <returns></returns>
public static Assembly NewClass(List<string> AttributesStr)
{
//建置Class
var Str = "public class dynamicclass\n";
Str += "{\n";
//建置屬性
for (var i = 0; i < AttributesStr.Count; i++)
{
Str += "public string " + AttributesStr[i] + " { get; set; }\n";
}
Str += "}";
//建立編譯器物件
var provider = new CSharpCodeProvider();
//建立編譯參數
var paras = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true
};
//偵錯監控訊息
Debug.WriteLine(Str);
//開始編譯 動態Class
var result = provider.CompileAssemblyFromSource(paras, Str);
//取得編譯後的 動態Class
return result.CompiledAssembly;
}
/// <summary>
/// 設定屬性值
/// </summary>
/// <param name="objclass"></param>
/// <param name="propertyname"></param>
/// <param name="value"></param>
public static void ReflectionSetProperty(object objclass, string propertyname, string value)
{
var infos = objclass.GetType().GetProperties();
foreach (var info in infos)
{
if (info.Name == propertyname && info.CanWrite)
{
info.SetValue(objclass, value, null);
}
}
}
/// <summary>
/// 取得屬性值
/// </summary>
/// <param name="objclass"></param>
/// <param name="propertyname"></param>
public static void ReflectionGetProperty(object objclass, string propertyname)
{
var infos = objclass.GetType().GetProperties();
foreach (var info in infos)
{
if (info.Name == propertyname && info.CanRead)
{
System.Console.WriteLine(info.GetValue(objclass, null));
}
}
}
}
}
有檢查過 listclass.Add(NewClassModel); 的內容正確嗎?
或許是要改成下式,兩筆資料要 Add 兩次,猜的.....
if (NewClassModel != null)
{
//設定值1
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學號", "Test1");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學生姓名", "Test2");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "性別", "Test3");
//
listclass.Add(NewClassModel);
//設定值2
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學號", "Test4");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "學生姓名", "Test5");
DynamicClassHelper.ReflectionSetProperty(NewClassModel, "性別", "Test6");
//
listclass.Add(NewClassModel);
}
有成功兩行~
但是第一列卻是 Test4 Test5 Test6
而不是 Test1 Test2 Test3
若拆成兩個不同動態類別~可以存不同變數@@a
莫非動態類別只能存一種變數?!
所以這文章裡面這段程式碼~大概也是要重新建構吧?!
哈~~我又邏輯推論正確了~ok了!
答案就給你了
有想過.....
1.儲存格可能要指定線條與顏色的問題嗎?
2.數字小於 0 要紅色字標示?
3.文字靠左,數字靠右,要顯示千分號等問題 ?
可能要先想一下,萬一做不到,
那是不是又要換其他解法。
沒關係~先解決~匯出都要先做好空白的Excel檔案的寫入問題~
我這樣操作~就不需要準備空白Excel檔案了~
以及欄位可以不用固定設定了~
這樣我從資料庫撈欄位就可以隨機變動了~
不用受限在固定的Class欄位名稱~
儲存格特效~變色問題~
NPOI都可以解決Excel問題~
之後再進階練習儲存格操作^_^
參考 NPOI 操作 儲存格 設定
https://ithelp.ithome.com.tw/articles/10231282
原來你是輸出成xlsx才要動態欄位,我一直以為你連存資料都要動態欄位。
匯出我個人比較偏愛2個for迴圈解決就是了。
畢竟你還是從資料庫出來,類型什麼的都是依照資料庫,沒必要一定要映射成model。
froce
哈~我是想要突破 為什麼 Class 只能固定屬性,卻不能自由加減屬性
基本上Excel可以用好幾種方式操作讀寫~
畢竟現在網路教學的 Class 方式,我發現都是固定屬性的~
卻無法動態屬性
https://blog.darkthread.net/blog/expandoobject/
有版本限制。
不過還是要注意下面的結論: 動態語言寫起來很簡潔,但卻失去了編譯期語法檢查的保護
如果後續要操作model,用反射應該也會遇到同樣的問題。
沒在寫C#不清楚就是了。
另外你公司有在做程式碼檢查嗎?有點好奇這樣寫會不會過。
這理論上會有問題。
他們看不懂我寫啥..覺得功能跑就好
畢竟這套是拿別人來用的~寫這套作者的又跑了(55歲退休不做)~
才找我來處理維護..(聽說找工程師好幾個月了)
重點不是在有無辦法使用動態屬性,而是你的目的。
自己想好方法,就限制了自己,有時候不一定能找到做法。
您動態class的屬性名稱相同後面設定的值自然就會蓋掉前面的,不過不清楚您的實際需求,假如只是要透過NPOI mapper塞資料到excel也不一定要用動態class,可以用匿名型別試試看!