Dre*_*fer 7 .net c# excel interop
当我将整个表写入excel工作表时,我知道一次使用整个Range,而不是写入单个单元格.但是,有没有办法指定格式,因为我正在填充我要导出到Excel的数组?
这就是我现在所做的:
object MissingValue = System.Reflection.Missing.Value;
Excel.Application excel = new Excel.Application();
int rows = 5;
int cols = 5;
int someVal;
Excel.Worksheet sheet = (Excel.Worksheet)excel.Workbooks.Add(MissingValue).Sheets[1];
Excel.Range range = sheet.Range("A1", sheet.Cells(rows,cols));
object[,] rangeData = new object[rows,cols];
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
someVal = r + c;
rangeData[r,c] = someVal.ToString();
}
}
range.set_Value(MissingValue, rangeData);
Run Code Online (Sandbox Code Playgroud)
现在假设我希望将这些数字中的一些格式化为百分比.我知道我可以逐个单元地返回并更改格式,但这似乎打败了使用单个Range.set_Value()调用的整个目的.我可以使我的rangeData [,]结构包含格式化信息,这样当我调用set_Value()时,单元格的格式是我想要的吗?
为了澄清,我知道我可以设置整个Excel.Range对象的格式.我想要的是为内部循环中指定的每个单元格指定不同的格式.
这是迄今为止我找到的最好的“解决方案”。这不是我一直在寻找的涅槃,但它比单独设置每个单元格的格式要快得多。
// 0-based indexes
static string RcToA1(int row, int col)
{
string toRet = "";
int mag = 0;
while(col >= Math.Pow(26, mag+1)){mag++;}
while (mag>0)
{
toRet += System.Convert.ToChar(64 + (byte)Math.Truncate((double)(col/(Math.Pow(26,mag)))));
col -= (int)Math.Truncate((double)Math.Pow(26, mag--));
}
toRet += System.Convert.ToChar(65 + col);
return toRet + (row + 1).ToString();
}
static Random rand = new Random(DateTime.Now.Millisecond);
static string RandomExcelFormat()
{
switch ((int)Math.Round(rand.NextDouble(),0))
{
case 0: return "0.00%";
default: return "0.00";
}
}
struct ExcelFormatSpecifier
{
public object NumberFormat;
public string RangeAddress;
}
static void DoWork()
{
List<ExcelFormatSpecifier> NumberFormatList = new List<ExcelFormatSpecifier>(0);
object[,] rangeData = new object[rows,cols];
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
someVal = r + c;
rangeData[r,c] = someVal.ToString();
NumberFormatList.Add(new ExcelFormatSpecifier
{
NumberFormat = RandomExcelFormat(),
RangeAddress = RcToA1(rowIndex, colIndex)
});
}
}
range.set_Value(MissingValue, rangeData);
int max_format = 50;
foreach (string formatSpecifier in NumberFormatList.Select(p => p.NumberFormat).Distinct())
{
List<string> addresses = NumberFormatList.Where(p => p.NumberFormat == formatSpecifier).Select(p => p.RangeAddress).ToList();
while (addresses.Count > 0)
{
string addressSpecifier = string.Join(",", addresses.Take(max_format).ToArray());
range.get_Range(addressSpecifier, MissingValue).NumberFormat = formatSpecifier;
addresses = addresses.Skip(max_format).ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
基本上发生的事情是,我在 NumberFormatList 中保留每个单元格的格式信息列表(每个元素还保存其适用范围的 A1 样式地址)。最初的想法是,对于工作表中的每种不同格式,我应该能够构建仅包含这些单元格的 Excel.Range 并在一次调用中将该格式应用于该范围。这会将 NumberFormat 的访问次数从(可能)数千次减少到只有几次(无论您有多少种不同的格式)。
然而,我遇到了一个问题,因为您显然无法从任意长的单元格列表中构造一个范围。经过一些测试,我发现限制在 50 到 100 个单元格之间,可用于定义任意范围(如 range.get_Range("A1,B1,C1,A2,AA5,.....")因此,一旦我获得了要应用格式的所有单元格的列表,我就会有一个最后的 while() 循环,一次将格式应用到其中 50 个单元格。
这并不理想,但它仍然可以将 NumberFormat 的访问次数减少多达 50 倍,这很重要。构建没有任何格式信息的电子表格(仅使用 range.set_Value())大约需要 3 秒。当我一次应用 50 个单元格的格式时,时间会延长到大约 10 秒。当我将格式信息单独应用到每个单元格时,电子表格需要 2 分钟多才能完成构建!
归档时间: |
|
查看次数: |
10463 次 |
最近记录: |