帝国CMS模板大全
www.admin99.cn
www.92cms.cn 帝国CMS模板下载站!,情怀,养站,二次开发!源码需求比较大的一站式会员下载,价更省!!!

.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.Replace( "[]" , 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]字符串是不能做求和运算的)。 

dy(“nrwz”);

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《.NET的深复制方法(以C#语言为例)》
文章链接:https://www.admin99.cn/7480
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
QQ站长交流群:953950264

登录

找回密码

注册