C# 如何使用Excel.Range.set_Value()指定单个单元格的格式
当我将整个表格写入excel工作表时,我知道要同时处理整个范围,而不是写入单个单元格。但是,在填充要导出到Excel的数组时,是否有方法指定格式 我现在做的是:C# 如何使用Excel.Range.set_Value()指定单个单元格的格式,c#,.net,excel,interop,C#,.net,Excel,Interop,当我将整个表格写入excel工作表时,我知道要同时处理整个范围,而不是写入单个单元格。但是,在填充要导出到Excel的数组时,是否有方法指定格式 我现在做的是: object MissingValue = System.Reflection.Missing.Value; Excel.Application excel = new Excel.Application(); int rows = 5; int cols = 5; int someVal; Excel.Worksheet sheet
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);
object MissingValue=System.Reflection.Missing.Value;
Excel.Application Excel=新建Excel.Application();
int行=5;
int cols=5;
int-someVal;
Excel.Worksheet sheet=(Excel.Worksheet)Excel.Workbooks.Add(MissingValue.Sheets[1];
Excel.Range范围=sheet.Range(“A1”,sheet.Cells(行,列));
对象[,]范围数据=新对象[行,列];
对于(int r=0;r
现在假设我想把其中一些数字格式化为百分比。我知道我可以逐个单元格返回并更改格式,但这似乎违背了使用单个Range.set_Value()调用的全部目的。我是否可以使rangeData[,]结构包含格式信息,以便在调用set_Value()时,单元格的格式符合我的要求
为了澄清,我知道我可以为整个Excel.Range对象设置格式。我想要的是为每个单元格指定不同的格式,在内部循环中指定。您可以对范围应用格式,然后用无法在
对象[,]中指定格式的值填充它。
数组您可以通过
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
Excel.Range r2 = sheet.Cells( r, c );
r2.xxxx = "";
}
}
for(int r=0;r
一旦你有了r2
,你就可以随心所欲地更改单元格格式。因此,这是迄今为止我找到的最好的“解决方案”。这不是我想要的涅磐,但它比为每个细胞单独设置格式要快得多
// 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();
}
}
}
//基于0的索引
静态字符串RcToA1(整数行,整数列)
{
字符串toRet=“”;
int-mag=0;
而(col>=Math.Pow(26,mag+1)){mag++;}
while(mag>0)
{
toRet+=System.Convert.ToChar(64+(字节)Math.Truncate((双精度)(col/(Math.Pow(26,mag ')));
col-=(int)Math.Truncate((double)Math.Pow(26,mag-);
}
toRet+=系统转换为ToChar(65+列);
返回toRet+(行+1).ToString();
}
静态随机兰德=新随机数(DateTime.Now.毫秒);
静态字符串格式()
{
开关((int)Math.Round(rand.NextDouble(),0))
{
案例0:返回“0.00%”;
默认值:返回“0.00”;
}
}
结构ExcelFormatSpecifier
{
公共对象编号格式;
公共字符串地址;
}
静态空心榫钉()
{
列表编号格式列表=新列表(0);
对象[,]范围数据=新对象[行,列];
对于(int r=0;rp.NumberFormat.Distinct())中的字符串格式说明符)
{
List addresses=NumberFormatList.Where(p=>p.NumberFormat==formatSpecifier)。选择(p=>p.RangeAddress.ToList();
而(addresses.Count>0)
{
string addressSpecifier=string.Join(“,”,addresses.Take(max_格式).ToArray());
range.get_range(addressSpecifier,MissingValue).NumberFormat=formatSpecifier;
地址=地址.Skip(max_格式).ToList();
}
}
}
基本上,我在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分钟才能完成构建!我意识到这将完成工作,但我正试图保持对abs的Excel互操作的调用次数绝对最小值。在内部循环中应用格式将有效,但会非常慢。虽然我接受了自己的答案,但我决定使用Excel automation来编写文件是一个糟糕的计划。接下来,我将使用Excel软件包库直接编写.xlsx文件+一段漂亮的代码;)我不知道可以使用formatSpecifier来设置单元格范围。