最快的 excel 复制大范围的互操作方式,对其进行排序并删除不必要的列
Quickest excel interop way to copy a big range, sort it and remove unnecessay columns
我有一个 c# 代码可以生成一个非常大的数组,我将其写入 excel 工作表。然后我在同一个工作簿中使用相同的大数组创建另一个工作表,并对后者进行排序:
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApp1
{
class Program
{
static object[,] returnDummyVariant()
{
object[,] res = new object[4,3];
res[0, 0] = "Surname";
res[0, 1] = "Height";
res[0, 2] = "Age";
res[1, 0] = "Julian";
res[1, 1] = "185";
res[1, 2] = "39";
res[2, 0] = "Mark";
res[2, 1] = "173";
res[2, 2] = "63";
res[3, 0] = "Patrick";
res[3, 1] = "193";
res[3, 2] = "23";
return res;
}
private static Excel.Range WriteTopLeft(object[,] variant, Excel.Range topLeft)
{
if (variant == null) return null;
int nL = variant.GetLength(0);
int nC = variant.GetLength(1);
if (nL * nC == 0) return null;
var worksheet = topLeft.Worksheet;
var writeRange = worksheet.Range[topLeft, topLeft.Offset[nL - 1, nC - 1]];
writeRange.Value2 = variant;
return writeRange;
}
static void Main(string[] args)
{
Application excel = new Application();
string path = @"paht\to\file\Book1.xlsx";
Workbook wb = excel.Workbooks.Open(path);
var wsData = (Excel.Worksheet)wb.Worksheets.Item[1];
wsData.Name = "Data";
var variant = returnDummyVariant();
var rData = WriteTopLeft(variant, wsData.Cells[1, 1]);
int rows = rData.Rows.Count;
int columns = rData.Columns.Count;
var ws = (Excel.Worksheet)wb.Worksheets.Add();
ws.Name = "Sorted Data";
rData = WriteTopLeft(variant, ws.Cells[1, 1]);
rData.Sort(rData.Columns[2, Type.Missing], Excel.XlSortOrder.xlDescending,
Type.Missing, Excel.XlSortOrder.xlAscending, Excel.XlSortOrder.xlAscending,
Type.Missing, Excel.XlSortOrder.xlAscending,
Excel.XlYesNoGuess.xlGuess, Type.Missing, Type.Missing,
Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal);
wb.Save();
wb.Close();
}
}
}
.Sort
位触发异常:System.Runtime.InteropServices.COMException: 'Reference isn't valid.'
,我找不到原因。
我在这里和那里尝试了几次更正,但都没有成功。
首先,作为一种好的做法,您应该捕获抛出的异常并查找任何其他信息 - 这将是此异常的 HRESULT。
虽然在这种情况下,获得的信息并不是特别有用 - 错误代码 0x800a03ec,用于多个故障。
查看 Sort 方法的文档,我发现您的第 4 个参数不正确 - 它应该只在排序数据透视表时使用,否则应该作为 Type.Missing.[=15 传递=]
rData.Sort(rData.Columns[2, Type.Missing], Excel.XlSortOrder.xlDescending,
Type.Missing, Type.Missing, Excel.XlSortOrder.xlAscending,
Type.Missing, Excel.XlSortOrder.xlAscending,
Excel.XlYesNoGuess.xlGuess, Type.Missing, Type.Missing,
Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal);
您还可以通过使用命名参数来简化方法调用,然后它将为您省略的参数使用适当的默认值:
rData.Sort(rData.Columns[2, Type.Missing],
XlSortOrder.xlDescending,
Header: XlYesNoGuess.xlGuess,
Orientation: XlSortOrientation.xlSortColumns);
此外,您应该退出应用程序 - excel.Quit();在你的申请结束时。默认情况下,Excel 的实例会打开但不会显示 - 如果您不退出该应用程序,它将保持打开状态,直到您关闭您的 PC - 多次尝试 运行 您的应用程序然后打开启动 TaskManager,您将看到相同数量的 Excel 个进程。
如果您的应用程序像上面的代码一样相对较小,那么在整理 Excel COM 对象方面应该没有任何问题,如果您的代码更复杂并且您使用了很多对象(范围、工作表)等都是 COM 对象)那么你应该确保它们通过使用 Marshal.ReleaseComObject 并将引用设置为 null 从内存中释放 - 有些人也建议调用 GC.Collect 两次 - 这里有很多讨论:How do I properly clean up Excel interop objects?
我有一个 c# 代码可以生成一个非常大的数组,我将其写入 excel 工作表。然后我在同一个工作簿中使用相同的大数组创建另一个工作表,并对后者进行排序:
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApp1
{
class Program
{
static object[,] returnDummyVariant()
{
object[,] res = new object[4,3];
res[0, 0] = "Surname";
res[0, 1] = "Height";
res[0, 2] = "Age";
res[1, 0] = "Julian";
res[1, 1] = "185";
res[1, 2] = "39";
res[2, 0] = "Mark";
res[2, 1] = "173";
res[2, 2] = "63";
res[3, 0] = "Patrick";
res[3, 1] = "193";
res[3, 2] = "23";
return res;
}
private static Excel.Range WriteTopLeft(object[,] variant, Excel.Range topLeft)
{
if (variant == null) return null;
int nL = variant.GetLength(0);
int nC = variant.GetLength(1);
if (nL * nC == 0) return null;
var worksheet = topLeft.Worksheet;
var writeRange = worksheet.Range[topLeft, topLeft.Offset[nL - 1, nC - 1]];
writeRange.Value2 = variant;
return writeRange;
}
static void Main(string[] args)
{
Application excel = new Application();
string path = @"paht\to\file\Book1.xlsx";
Workbook wb = excel.Workbooks.Open(path);
var wsData = (Excel.Worksheet)wb.Worksheets.Item[1];
wsData.Name = "Data";
var variant = returnDummyVariant();
var rData = WriteTopLeft(variant, wsData.Cells[1, 1]);
int rows = rData.Rows.Count;
int columns = rData.Columns.Count;
var ws = (Excel.Worksheet)wb.Worksheets.Add();
ws.Name = "Sorted Data";
rData = WriteTopLeft(variant, ws.Cells[1, 1]);
rData.Sort(rData.Columns[2, Type.Missing], Excel.XlSortOrder.xlDescending,
Type.Missing, Excel.XlSortOrder.xlAscending, Excel.XlSortOrder.xlAscending,
Type.Missing, Excel.XlSortOrder.xlAscending,
Excel.XlYesNoGuess.xlGuess, Type.Missing, Type.Missing,
Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal);
wb.Save();
wb.Close();
}
}
}
.Sort
位触发异常:System.Runtime.InteropServices.COMException: 'Reference isn't valid.'
,我找不到原因。
我在这里和那里尝试了几次更正,但都没有成功。
首先,作为一种好的做法,您应该捕获抛出的异常并查找任何其他信息 - 这将是此异常的 HRESULT。
虽然在这种情况下,获得的信息并不是特别有用 - 错误代码 0x800a03ec,用于多个故障。
查看 Sort 方法的文档,我发现您的第 4 个参数不正确 - 它应该只在排序数据透视表时使用,否则应该作为 Type.Missing.[=15 传递=]
rData.Sort(rData.Columns[2, Type.Missing], Excel.XlSortOrder.xlDescending,
Type.Missing, Type.Missing, Excel.XlSortOrder.xlAscending,
Type.Missing, Excel.XlSortOrder.xlAscending,
Excel.XlYesNoGuess.xlGuess, Type.Missing, Type.Missing,
Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal,
Excel.XlSortDataOption.xlSortNormal);
您还可以通过使用命名参数来简化方法调用,然后它将为您省略的参数使用适当的默认值:
rData.Sort(rData.Columns[2, Type.Missing],
XlSortOrder.xlDescending,
Header: XlYesNoGuess.xlGuess,
Orientation: XlSortOrientation.xlSortColumns);
此外,您应该退出应用程序 - excel.Quit();在你的申请结束时。默认情况下,Excel 的实例会打开但不会显示 - 如果您不退出该应用程序,它将保持打开状态,直到您关闭您的 PC - 多次尝试 运行 您的应用程序然后打开启动 TaskManager,您将看到相同数量的 Excel 个进程。
如果您的应用程序像上面的代码一样相对较小,那么在整理 Excel COM 对象方面应该没有任何问题,如果您的代码更复杂并且您使用了很多对象(范围、工作表)等都是 COM 对象)那么你应该确保它们通过使用 Marshal.ReleaseComObject 并将引用设置为 null 从内存中释放 - 有些人也建议调用 GC.Collect 两次 - 这里有很多讨论:How do I properly clean up Excel interop objects?