iT邦幫忙

0

請問如何讓動態class類別的資料,可以寫到第二列以上?(Excel)

  • 分享至 

  • xImage

承上次提問,是乎都沒回答

請問如何讓class類別的欄位動態建立?
https://ithelp.ithome.com.tw/questions/10215657

我自己再次Google找答案看看~有無讓class類別的欄位動態建立

經測試將Class屬性定義簡單化,在Excel依舊是一樣的欄位

https://ithelp.ithome.com.tw/upload/images/20240512/20061369fECJOyGF2o.png

所以找到這網址教學,再根據開發軟體的智能建議修正程式碼

C#匿名对象(转JSON)互转、动态添加属性
https://www.cnblogs.com/elves/p/6087186.html

成功設置動態class類別的欄位動態建立

但問題出現這個動態類別,不會增加寫第二列的資料

請問各位高手如何修改呢?!

https://ithelp.ithome.com.tw/upload/images/20240512/20061369WB9cMSvCwB.png

原本寫入Excel問題如下

https://ithelp.ithome.com.tw/upload/images/20240512/20061369A0v77ZPHW9.png

希望能變成以下結果的畫面

https://ithelp.ithome.com.tw/upload/images/20240512/20061369vmLhKXDgK0.png

另外附上該頁的測試程式碼

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));
                }
            }
        }
    }
}

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
rogeryao
iT邦超人 7 級 ‧ 2024-05-12 16:39:33
最佳解答

有檢查過 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

https://ithelp.ithome.com.tw/upload/images/20240512/20061369yQC1KKX3Li.png

若拆成兩個不同動態類別~可以存不同變數@@a
莫非動態類別只能存一種變數?!

https://ithelp.ithome.com.tw/upload/images/20240512/20061369q8h1hhm4bS.png

https://ithelp.ithome.com.tw/upload/images/20240512/200613692rF22CIKH7.png

所以這文章裡面這段程式碼~大概也是要重新建構吧?!

https://ithelp.ithome.com.tw/upload/images/20240512/20061369BpEeZFkoxp.png

哈~~我又邏輯推論正確了~ok了!
答案就給你了/images/emoticon/emoticon12.gif
https://ithelp.ithome.com.tw/upload/images/20240512/20061369xVV6s4ukRH.png

https://ithelp.ithome.com.tw/upload/images/20240512/20061369KD0O4M7WdQ.png

rogeryao iT邦超人 7 級 ‧ 2024-05-12 18:51:58 檢舉

有想過.....
1.儲存格可能要指定線條與顏色的問題嗎?
2.數字小於 0 要紅色字標示?
3.文字靠左,數字靠右,要顯示千分號等問題 ?

可能要先想一下,萬一做不到,
那是不是又要換其他解法。

沒關係~先解決~匯出都要先做好空白的Excel檔案的寫入問題~
我這樣操作~就不需要準備空白Excel檔案了~
以及欄位可以不用固定設定了~
這樣我從資料庫撈欄位就可以隨機變動了~
不用受限在固定的Class欄位名稱~

儲存格特效~變色問題~
NPOI都可以解決Excel問題~
之後再進階練習儲存格操作^_^

參考 NPOI 操作 儲存格 設定
https://ithelp.ithome.com.tw/articles/10231282

froce iT邦大師 1 級 ‧ 2024-05-13 10:04:03 檢舉

原來你是輸出成xlsx才要動態欄位,我一直以為你連存資料都要動態欄位。
匯出我個人比較偏愛2個for迴圈解決就是了。
畢竟你還是從資料庫出來,類型什麼的都是依照資料庫,沒必要一定要映射成model。

froce
哈~我是想要突破 為什麼 Class 只能固定屬性,卻不能自由加減屬性
基本上Excel可以用好幾種方式操作讀寫~

畢竟現在網路教學的 Class 方式,我發現都是固定屬性的~
卻無法動態屬性/images/emoticon/emoticon10.gif

froce iT邦大師 1 級 ‧ 2024-05-13 11:02:33 檢舉

https://blog.darkthread.net/blog/expandoobject/
有版本限制。
不過還是要注意下面的結論: 動態語言寫起來很簡潔,但卻失去了編譯期語法檢查的保護
如果後續要操作model,用反射應該也會遇到同樣的問題。
沒在寫C#不清楚就是了。

另外你公司有在做程式碼檢查嗎?有點好奇這樣寫會不會過。
這理論上會有問題。

他們看不懂我寫啥..覺得功能跑就好/images/emoticon/emoticon06.gif

畢竟這套是拿別人來用的~寫這套作者的又跑了(55歲退休不做)~
才找我來處理維護..(聽說找工程師好幾個月了)

0
huangsb
iT邦好手 1 級 ‧ 2024-05-13 10:39:24

重點不是在有無辦法使用動態屬性,而是你的目的。

自己想好方法,就限制了自己,有時候不一定能找到做法。

我的目的很簡單,就想了解程式架構可不可以突破限制

舉例來說, 醫生 有無辦法做 台積電工程師

一般來說隔行如隔山,只要有辦法穿山越嶺,就是突破

除非空降掛總經理/images/emoticon/emoticon10.gif

v60i iT邦新手 3 級 ‧ 2024-05-13 20:47:37 檢舉

醫生有沒有辦法做台積電工程師我是不知道,但我知道醫生可以開醫院賺錢當董事長

1
breezy89757
iT邦新手 5 級 ‧ 2024-05-16 23:39:20

https://ithelp.ithome.com.tw/upload/images/20240516/20167158X2Ck8csfqr.png
您動態class的屬性名稱相同後面設定的值自然就會蓋掉前面的,不過不清楚您的實際需求,假如只是要透過NPOI mapper塞資料到excel也不一定要用動態class,可以用匿名型別試試看!

需求只是想知道 class 的屬性 能不能 動態設定(增加或減少)

可以,反射跟DynamicObject都可以達成

我要發表回答

立即登入回答