程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> .NET的深復制辦法(以C#說話為例)

.NET的深復制辦法(以C#說話為例)

編輯:C#入門知識

.NET的深復制辦法(以C#說話為例)。本站提示廣大學習愛好者:(.NET的深復制辦法(以C#說話為例))文章只能為提供參考,不一定能成為您想要的結果。以下是.NET的深復制辦法(以C#說話為例)正文


許多時刻我們復制一個對象實例A到實例B,在用實例B去做其他工作的時刻,會對實例B停止修正,為包管對B的修正不會影響到A的正常應用,就須要應用到深復制。

我在網上搜到一些深復制的辦法,同時寫了幾組例子對這些辦法停止測試。

我的操作體系版本為Win7旗艦版,.NET Framework版本是4.5

測試法式

我建了一個C#窗體運用法式(Winform),其主窗口FormMain的Load函數內容以下:

private void FormMain_Load(object sender, EventArgs e)
{
 //測試1:深度復制 自界說類
 try
 {
  Console.WriteLine("=== 深度復制 自界說類 ===");
  TestClass test1 = new TestClass();
  test1.a = 10;
  test1.b = "hello world!";
  test1.c = new string[] { "x", "y", "z" };
  TestClass test2 = new TestClass();
  test2.a = 11;
  test2.b = "hello world2!";
  test2.c = new string[] { "i", "j", "k" };
  test1.d = test2;
  Console.WriteLine("---test1_start---");
  Console.WriteLine(test1);
  Console.WriteLine("---test1_end---");
  TestClass test3 = (TestClass)DataManHelper.DeepCopyObject(test1);
  Console.WriteLine("---test3_start---");
  Console.WriteLine(test3);
  Console.WriteLine("---test3_end---");
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.ToString());
 }

    //測試2:深度復制 可序列化的自界說類
   

 try
 {
  Console.WriteLine("=== 深度復制 可序列化的自界說類 ===");
  TestClassWithS test1 = new TestClassWithS();
  test1.a = 10;
  test1.b = "hello world!";
  test1.c = new string[] { "x", "y", "z" };
  TestClassWithS test2 = new TestClassWithS();
  test2.a = 11;
  test2.b = "hello world2!";
  test2.c = new string[] { "i", "j", "k" };
  test1.d = test2;
  Console.WriteLine("---test1_start---");
  Console.WriteLine(test1);
  Console.WriteLine("---test1_end---");
  TestClassWithS test3 = (TestClassWithS)DataManHelper.DeepCopyObject(test1);
  Console.WriteLine("---test3_start---");
  Console.WriteLine(test3);
  Console.WriteLine("---test3_end---");
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.ToString());
 }

    //測試3:深度復制 DataTable
  

 try
 {
  Console.WriteLine("=== 深度復制 DataTable ===");
  DataTable dtKirov = new DataTable("TestTable");
  dtKirov.Columns.Add("Col1");
  dtKirov.Columns.Add("Col2");
  dtKirov.Columns.Add("Col3");
  dtKirov.Rows.Add("1-1", "1-2", "1-3");
  dtKirov.Rows.Add("2-1", "2-2", "2-3");
  dtKirov.Rows.Add("3-1", "3-2", "3-3");
  Console.WriteLine("=== 復制前 ===");
  for (int i = 0; i < dtKirov.Columns.Count; i++)
  {
   Console.Write(dtKirov.Columns[i].ColumnName + "\t");
  }
  Console.WriteLine("\n-----------------");
  for (int i = 0; i < dtKirov.Columns.Count; i++)
  {
   for (int j = 0; j < dtKirov.Rows.Count; j++)
   {
    Console.Write(dtKirov.Rows[i][j].ToString() + "\t");
   }
   Console.WriteLine();
  }
  Console.WriteLine();
  DataTable dtDreadNought = (DataTable)DataManHelper.DeepCopyObject(dtKirov);
  Console.WriteLine("=== 復制後 ===");
  for (int i = 0; i < dtDreadNought.Columns.Count; i++)
  {
   Console.Write(dtDreadNought.Columns[i].ColumnName + "\t");
  }
  Console.WriteLine("\n-----------------");
  for (int i = 0; i < dtDreadNought.Columns.Count; i++)
  {
   for (int j = 0; j < dtDreadNought.Rows.Count; j++)
   {
    Console.Write(dtDreadNought.Rows[i][j].ToString() + "\t");
   }
   Console.WriteLine();
  }
  Console.WriteLine();
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.ToString());
 }

    //測試4:深度復制 TextBox
   

 try
 {
  Console.WriteLine("=== 深度復制 TextBox ===");
  txtTest.Text = "1234";
  Console.WriteLine("復制前:" + txtTest.Text);
  TextBox txtTmp = new TextBox();
  txtTmp = (TextBox)DataManHelper.DeepCopyObject(txtTest);
  Console.WriteLine("復制後:" + txtTmp.Text);
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.ToString());
 }

    //測試5:深度復制 DataGridView
 

 try
 {
  Console.WriteLine("=== 深度復制 DataGridView ===");
  DataGridView dgvTmp = new DataGridView();
  dgvTmp = (DataGridView)DataManHelper.DeepCopyObject(dgvTest);
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.ToString());
 }
}

個中txtTest是一個測試用的TextBox,dgvTmp是一個測試用的DataGridView,TestClass是一個自界說類,TestClassWithS是添加了Serializable特征的TestClass類,它們的詳細完成以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataCopyTest
{
 public class TestClass
 {
  public int a;
  public string b;
  public string[] c;
  public TestClass d;
  public override string ToString()
  {
   string s = "a:" + a + "\n";
   if (b != null)
   {
    s += "b:" + b + "\n";
   }
   if (c != null)
   {
    foreach (string tmps in c)
    {
     if (!string.IsNullOrWhiteSpace(tmps))
     {
      s += "c:" + tmps + "\n";
     }
    }
   }
   if (d != null)
   {
    s += d.ToString();
   }
   return s;
  }
 }

 //支撐序列化的TestClass
 [Serializable]
 public class TestClassWithS
 {
  public int a;
  public string b;
  public string[] c;
  public TestClassWithS d;
  public override string ToString()
  {
   string s = "a:" + a + "\n";
   if (b != null)
   {
    s += "b:" + b + "\n";
   }
   if (c != null)
   {
    foreach (string tmps in c)
    {
     if (!string.IsNullOrWhiteSpace(tmps))
     {
      s += "c:" + tmps + "\n";
     }
    }
   }
   if (d != null)
   {
    s += d.ToString();
   }
   return s;
  }
 }
}

我對每一個搜來的深復制辦法,都用了這五個類的實例停止深復制測試,這五個類的特點以下:

I、對自界說類TestClass停止深復制測試

II、對自界說類TestClassWithS停止深復制測試,TestClassWithS是添加了Serializable特征的TestClass類

III、對DataTable停止深復制測試

IV、對控件TextBox停止深復制測試

V、對控件DataGridView停止深復制測試

我們經由過程完成辦法DataManHelper.DeepCopyObject來停止測試

測試深復制辦法1

應用二進制流的序列化與反序列化深度復制對象

public static object DeepCopyObject(object obj)
{
 BinaryFormatter Formatter = new BinaryFormatter(null, 
  new StreamingContext(StreamingContextStates.Clone));
 MemoryStream stream = new MemoryStream();
 Formatter.Serialize(stream, obj);
 stream.Position = 0;
 object clonedObj = Formatter.Deserialize(stream);
 stream.Close();
 return clonedObj;
}

五個場景的測試成果為:

I、觸發異常SerializationException,緣由是該類不支撐序列化

“System.Runtime.Serialization.SerializationException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.Runtime.Serialization.SerializationException: 法式集“DataCopyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中的類型“DataCopyTest.TestClass”未標志為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, S“DataCopyTest.vshost.exe”(托管(v4.0.30319)): 已加載“C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Numerics\v4.0_4.0.0.0__b77a5c561934e089\System.Numerics.dll”
erializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 37
II、可正常復制 (√)

III、可正常復制 (√)

IV、觸發異常SerializationException,緣由是該類不支撐序列化

“System.Runtime.Serialization.SerializationException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.Runtime.Serialization.SerializationException: 法式集“System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中的類型“System.Windows.Forms.TextBox”未標志為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 128
V、觸發異常SerializationException,緣由是該類不支撐序列化

“System.Runtime.Serialization.SerializationException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.Runtime.Serialization.SerializationException: 法式集“System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中的類型“System.Windows.Forms.DataGridView”未標志為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 141
結論:應用序列化與反序列化到二進制流的辦法深復制對象,只要在該對象支撐Serializable特征時才可以使用

測試深復制辦法2

public static object DeepCopyObject(object obj)
{
 Type t = obj.GetType();
 PropertyInfo[] properties = t.GetProperties();
 Object p = t.InvokeMember("", System.Reflection.BindingFlags.CreateInstance, null, obj, null);
 foreach (PropertyInfo pi in properties)
 {
  if (pi.CanWrite)
  {
   object value = pi.GetValue(obj, null);
   pi.SetValue(p, value, null);
  }
 }
 return p;
}

五個場景的測試成果為:

I、不會觸發異常,但成果完整毛病

II、不會觸發異常,但成果完整毛病

III、不會觸發異常,但成果完整毛病

IV、Text字段賦值成果准確,但其他內容不克不及包管

V、觸發異常ArgumentOutOfRangeException、TargetInvocationException

“System.ArgumentOutOfRangeException”類型的第一次機遇異常在 System.Windows.Forms.dll 中產生
“System.Reflection.TargetInvocationException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.Reflection.TargetInvocationException: 挪用的目的產生了異常。 ---> System.ArgumentOutOfRangeException: 指定的參數已超越有用值的規模。
參數名: value
   在 System.Windows.Forms.DataGridView.set_FirstDisplayedScrollingColumnIndex(Int32 value)
   --- 外部異常客棧跟蹤的開頭 ---
   在 System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   在 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   在 System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   在 System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 29
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 141
結論:應用這類辦法停止所謂深復制,完整是自尋逝世路!

測試深復制辦法3

public static object DeepCopyObject(object obj)
{
 if (obj != null)
 {
  object result = Activator.CreateInstance(obj.GetType());
  foreach (FieldInfo field in obj.GetType().GetFields())
  {
   if (field.FieldType.GetInterface("IList", false) == null)
   {
    field.SetValue(result, field.GetValue(obj));
   }
   else
   {
    IList listObject = (IList)field.GetValue(result);
    if (listObject != null)
    {
     foreach (object item in ((IList)field.GetValue(obj)))
     {
      listObject.Add(DeepCopyObject(item));
     }
    }
   }
  }
  return result;
 }
 else
 {
  return null;
 }
}

五個場景的測試成果為:

I、可正常復制(√)

II、可正常復制(√)

III、未觸發異常, 復制後DataTable無行列

IV、未觸發異常,Text字段未賦值

V、未觸發異常

結論:這個辦法只實用於深復制具有簡略構造的類(如類中只要基本字段、數組等),關於不支撐序列化的對象也能夠停止深復制。

測試深復制辦法4

這段代碼起源同辦法3

public static object DeepCopyObject(object obj)
{
 if (obj == null)
  return null;
 Type type = obj.GetType();

 if (type.IsValueType || type == typeof(string))
 {
  return obj;
 }
 else if (type.IsArray)
 {
  Type elementType = Type.GetType(
    type.FullName.WordStr("[]", string.Empty));
  var array = obj as Array;
  Array copied = Array.CreateInstance(elementType, array.Length);
  for (int i = 0; i < array.Length; i++)
  {
   copied.SetValue(DeepCopyObject(array.GetValue(i)), i);
  }
  return Convert.ChangeType(copied, obj.GetType());
 }
 else if (type.IsClass)
 {

  object toret = Activator.CreateInstance(obj.GetType());
  FieldInfo[] fields = type.GetFields(BindingFlags.Public |
     BindingFlags.NonPublic | BindingFlags.Instance);
  foreach (FieldInfo field in fields)
  {
   object fieldValue = field.GetValue(obj);
   if (fieldValue == null)
    continue;
   field.SetValue(toret, DeepCopyObject(fieldValue));
  }
  return toret;
 }
 else
  throw new ArgumentException("Unknown type");
}

五個場景的測試成果為:

I、可正常復制(√)

II、可正常復制(√)

III、觸發異常MissingMethodException

“System.MissingMethodException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.MissingMethodException: 沒無為該對象界說無參數的結構函數。
   在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
   在 System.Activator.CreateInstance(Type type)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 45
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 53
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 99
IV、未觸發異常,但Text字段也未賦值勝利

V、觸發異常MissingMethodException

“System.MissingMethodException”類型的第一次機遇異常在 mscorlib.dll 中產生
System.MissingMethodException: 沒無為該對象界說無參數的結構函數。
   在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
   在 System.Activator.CreateInstance(Type type)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 45
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\DataManHelper.cs:行號 53
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 地位 d:\MyPrograms\DataCopyTest\DataCopyTest\FormMain.cs:行號 141
結論:這個辦法的感化相似辦法3,只能深復制根本數據類型構成的類

詳細成績詳細剖析

從下面的例子可以看出,想找一個放之四海而皆准的方法去深復制一切對象是很艱苦的。一些應用高等說話特征(反射)的深復制辦法,即便可以在部門類上試用勝利,也沒法對一切的類都具有實足的掌握。是以我以為應當采用上面的方法處置對象的深復制成績:

1、關於由根本數據類型構成的類,為之打上Serializable標簽,直接應用序列化與反序列化的辦法停止深復制

2、其他較為龐雜的類型如DataGridView,可依據本身情形寫一個辦法停止深復制,之所以在這裡說要依據本身情形寫辦法,是由於在對許多類停止復制時,你只須要復制對你有效的屬性就好了。如TextBox控件中,只要Text一個屬性對你是有效的,假如你須要在復制後的對象頂用到Readonly等屬性的值,那末在你本身完成的復制辦法中,也加上對這些屬性的賦值便可。如許做還有一個利益,就是便利停止一些定制化的開辟。

以下面這段代碼,就是對DataGridView的一個近似的深復制,這段代碼將一個DataGridView(dgv)的內容復制到另外一個DataGridView(dgvTmp)中,然後將dgvTmp傳遞給相干函數用於將DataGridView中的內容輸入到Excel文檔:

DataGridView dgvTmp = new DataGridView();
dgvTmp.AllowUserToAddRows = false; //不許可用戶生成行,不然導出後會多出最初一行
for (int i = 0; i < dgv.Columns.Count; i++)
{
 dgvTmp.Columns.Add(dgv.Columns[i].Name, dgv.Columns[i].HeaderText);
 if (dgv.Columns[i].DefaultCellStyle.Format.Contains("N")) //使導出Excel文檔金額列可做SUM運算
 {
 dgvTmp.Columns[i].DefaultCellStyle.Format = dgv.Columns[i].DefaultCellStyle.Format;
 }
 if (!dgv.Columns[i].Visible)
 {
 dgvTmp.Columns[i].Visible = false;
 }
}
for (int i = 0; i < dgv.Rows.Count; i++)
{
 object[] objList = new object[dgv.Rows[i].Cells.Count];
 for (int j = 0; j < objList.Length; j++)
 {
 if (dgvTmp.Columns[j].DefaultCellStyle.Format.Contains("N"))
 {
 objList[j] = dgv.Rows[i].Cells[j].Value; //使導出Excel文檔金額列可做SUM運算
 }
 else
 {
 objList[j] = dgv.Rows[i].Cells[j].EditedFormattedValue; //數據字典按顯示文字導出
 }
 }
 dgvTmp.Rows.Add(objList);
}

這段代碼的特色以下:

1、DataGridView的屬性AllowUserToAddRows要設置成false,不然導出到Excel文檔後,會發明最初會多出一個空行。

2、我們在這裡標志了那些列是隱蔽列,如許在前面的處置中,假如要刪除這些列,那刪除的也是dgvTmp的列而不是dgv的列,掩護了原數據。

3、關於部門數據字典的翻譯,我們傳的不是Value而是EditedFormattedValue,這類方法直接應用了dgv在屏幕上顯示的翻譯後文字,而不是本來的數據字典值。

4、關於部門金額列,須要直接傳Value值,同時須要設置該列的DefaultCellStyle.Format,如許可以使得這些內容在以後輸入到Excel文檔後,可做乞降運算(Excel中相似“12,345.67”字符串是不克不及做乞降運算的)。 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved