为什么某些单元格没有发生着色,这与 "Cannot perform runtime binding" err msg 之间是否存在联系?
Why is some of the colorization of cells not occurring, and is there a connection between that and the "Cannot perform runtime binding" err msg?
我收到以下错误消息:
这发生在这段代码中:
private bool GetContractForDescription(string desc)
{
int DESCRIPTION_COL_NUM = 2;
int CONTRACT_COL_NUM = 7;
bool contractVal = false;
int rowsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
int colsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Columns.Count;
string colsUsedAsAlpha
ReportRunnerConstsAndUtils.GetExcelColumnName(colsUsed);
string endRange = string.Format("{0}{1}", colsUsedAsAlpha, rowsUsed);
Range sourceData = _xlBook.Worksheets["PivotData"].Range[string.Format("A2:{0}", endRange)];
// This is blowing up for some reason, so look for more detail on why
string currentDesc = string.Empty;
try
{
for (int i = 1; i <= rowsUsed; i++)
{
var dynamicCell = (Range)sourceData.Cells[i, DESCRIPTION_COL_NUM];
currentDesc = dynamicCell.Value2.ToString();
if (currentDesc.Equals(desc))
{
var dynamicContractCell = (Range)sourceData.Cells[i, CONTRACT_COL_NUM];
contractVal = (bool)dynamicContractCell.Value2;
break;
}
}
return contractVal;
}
catch (Exception ex)
{
MessageBox.Show(string.Format("currentDesc is {0}; exception is {1}", currentDesc, ex.Message));
}
return false;
}
更奇怪的是,我在特定情况下着色的 rows/cols 范围有一个 "hole cut out of it" 没有着色。
这里是有问题的源数据(中间行(156),最后一列的"TRUE"值是关键):
以下是数据在数据透视表上的呈现方式(中间数据块,第 293-297 行,是关键):
这是我用来透视源数据的代码:
private void AddPivotTable()
{
int FIRST_DESCRIPTION_ROW = 8;
int LINES_BETWEEN_DESCRIPTION_VALS = 5;
var pch = _xlBook.PivotCaches();
int rowsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
int colsUsed
_xlBook.Worksheets["PivotData"].UsedRange.Columns.Count;
string colsUsedAsAlpha
ReportRunnerConstsAndUtils.GetExcelColumnName(colsUsed);
string endRange = string.Format("{0}{1}", colsUsedAsAlph
rowsUsed);
Range sourceData
_xlBook.Worksheets["PivotData"].Range[string.Format("A1:{0}", endRange)];
PivotCache pc = pch.Create(XlPivotTableSourceType.xlDatabas
sourceData);
PivotTable pvt = pc.CreatePivotTable(_xlPivotTableSheet.Range["A6"
"PivotTable");
pvt.MergeLabels = true;
pvt.PivotFields("Description").Orientation
XlPivotFieldOrientation.xlRowField;
var monthField = pvt.PivotFields("MonthYr");
monthField.Orientation = XlPivotFieldOrientation.xlColumnField;
monthField.NumberFormat = "mmm yyyy";
monthField.DataRange.Interior.Color
ColorTranslator.ToOle(Color.LightBlue);
pvt.CompactLayoutColumnHeader = "Months";
pvt.CompactLayoutRowHeader = "Description";
pvt.AddDataField(pvt.PivotFields("TotalQty"), "Total Packages
XlConsolidationFunction.xlSum).NumberFormat = "###,##0";
pvt.AddDataField(pvt.PivotFields("TotalSales"), "Total Purchases
XlConsolidationFunction.xlSum).NumberFormat = "$#,##0";
PivotField avg = pvt.CalculatedFields().Add("Average Price
"=TotalSales/TotalQty", true);
avg.Orientation = XlPivotFieldOrientation.xlDataField;
// TODO: This calculation needs to change (it needs to actually
made a calculation, rather than just the TotalSales val)
pvt.CalculatedFields()._Add("PercentOfTotal", "=TotalSales");
pvt.AddDataField(pvt.PivotFields("PercentOfTotal"), "% of Total
Type.Missing).NumberFormat = "###.##";
. . .
...这是为相关项目着色的代码:
for (m = 1; m <= dataCnt + 1; m++)
{
string descVal = cellRng.Value2.ToString();
bool isContractItem = GetContractForDescription(descVal);
if (isContractItem)
{
mcellRng = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[rowcnt, 1],
_xlPivotTableSheet.Cells[rowcnt + 4, _grandTotalsColumn-1]];
mcellRng.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
mcellRng.EntireRow.RowHeight = 15;
}
. . .
我不明白着色代码(正上方)如何只能部分工作 - 如第二个屏幕截图所示,B 列中的前几个单元格是白色而不是黄色,其余的范围是。就好像有
此数据中的某些东西 "poison" 阻止了它被着色。
如果我生成较少的列(通过使用与 运行 报告不同的日期范围)它 运行 没有错误信息(但仍然有 "hole" 在范围内有问题)。
如果我只生成两个月就好了;但是如果我尝试六次(在任何一种情况下都存在 "problem" 记录),则会抛出异常...?!?
更新
当我注释掉整个 while 循环时,它 运行 没有错误,但是当然我没有将 ContractItems 着色。
有问题的 while 循环是:
while ((cellRng.Value2 != null) && cellRng.Value2.ToString() != "Total Total Packages")
{
cellRng.RowHeight = 25;
for (m = 1; m <= pivotTableRowCount; m++)
{
string descVal = cellRng.Value2.ToString();
bool isContractItem = GetContractForDescription(descVal);
if (isContractItem)
{
mcellRng = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[rowCounter, 1],
_xlPivotTableSheet.Cells[rowCounter + 4, _grandTotalsColumn - 1]];
mcellRng.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
mcellRng.EntireRow.RowHeight = 15;
}
rowCounter = rowCounter + LINES_BETWEEN_DESCRIPTION_VALS;
cellRng = (Range)_xlPivotTableSheet.Cells[rowCounter, 1];
}
}
这里的什么可能导致错误信息?
导致问题的不是 GetContractForDescription() 方法,因为像这样忽略它:
bool isContractItem = false; //GetContractForDescription(descVal);
...不会阻止错误消息。
更新 2
因为我的头在墙纸上撞了这么久,所以我决定 "go back to the coding board" 重新开始。我现在有这个代码来确定哪些项目是签约的:
List<String> contractItemDescs = GetContractItemDescriptions();
MessageBox.Show(contractItemDescs.Count.ToString());
. . .
private List<string> GetContractItemDescriptions()
{
int FIRST_PIVOTDATA_DATA_ROW = 2;
int DESCRIPTION_COLUMN = 2;
int CONTRACT_COLUMN = 7;
List<string> descriptionsOfContractedItems = new List<string>();
int pivotDataRowCount = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
// Loop through the data sheet, adding the Descriptions for all Contract Items to the generic list
for (int i = FIRST_PIVOTDATA_DATA_ROW; i <= pivotDataRowCount; i++)
{
Range contractItemCell = _xlPivotDataSheet.Cells[i, CONTRACT_COLUMN];
//if (contractItemCell.Value2.ToString() == "TRUE") <= seems to be the same logic as below, but this doesn't work, whereas the below code does...?!?
if (contractItemCell.Value2.ToString().ToUpper() != "FALSE")
{
Range descriptionCell = _xlPivotDataSheet.Cells[i, DESCRIPTION_COLUMN];
String desc = descriptionCell.Value2.ToString();
descriptionsOfContractedItems.Add(desc);
}
}
return descriptionsOfContractedItems;
}
这工作正常 - 消息框显示有效计数。但是请注意,注释掉的 "if" 语句。使用它,我什么也没有添加到列表中;使用我现在使用的看似类似的东西,我得到了 correct/expected 行为,但我不知道为什么。
我不太清楚为什么之前的代码不起作用,但我的猜测是逻辑通常过于混乱。我重构并简化了它(而不是尝试改编其他人编写的一些现有代码,我重新开始并做到了 "my way"),它现在工作得很好。新代码是:
private static readonly Color CONTRACT_ITEM_COLOR = Color.FromArgb(255, 255, 204);
. . .
private void AddPivotTable()
{
. . .
List<String> contractItemDescs = GetContractItemDescriptions();
ColorizeContractItemBlocks(contractItemDescs);
. . .
}
private List<string> GetContractItemDescriptions()
{
int FIRST_PIVOTDATA_DATA_ROW = 2;
int DESCRIPTION_COLUMN = 2;
int CONTRACT_COLUMN = 7;
List<string> descriptionsOfContractedItems = new List<string>();
int pivotDataRowCount = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
// Loop through the data sheet, adding the Descriptions for all Contract Items to the generic list
for (int i = FIRST_PIVOTDATA_DATA_ROW; i <= pivotDataRowCount; i++)
{
Range contractItemCell = _xlPivotDataSheet.Cells[i, CONTRACT_COLUMN];
if (contractItemCell.Value2.ToString().ToUpper() != "FALSE")
{
Range descriptionCell = _xlPivotDataSheet.Cells[i, DESCRIPTION_COLUMN];
String desc = descriptionCell.Value2.ToString();
descriptionsOfContractedItems.Add(desc);
}
}
return descriptionsOfContractedItems;
}
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 8;
int DESCRIPTION_COL = 1;
int ROWS_BETWEEN_DESCRIPTIONS = 5;
int rowsUsed = _xlBook.Worksheets["PivotTable"].UsedRange.Rows.Count;
int colsUsed = _xlBook.Worksheets["PivotTable"].UsedRange.Columns.Count;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
while (currentRowBeingExamined < rowsUsed)
{
Range descriptionCell = _xlPivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value2.ToString();
if (contractItemDescs.Contains(desc))
{
Range rangeToColorize = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[currentRowBeingExamined, 1],
_xlPivotTableSheet.Cells[currentRowBeingExamined + 4, colsUsed]];
rangeToColorize.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}
我收到以下错误消息:
这发生在这段代码中:
private bool GetContractForDescription(string desc)
{
int DESCRIPTION_COL_NUM = 2;
int CONTRACT_COL_NUM = 7;
bool contractVal = false;
int rowsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
int colsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Columns.Count;
string colsUsedAsAlpha
ReportRunnerConstsAndUtils.GetExcelColumnName(colsUsed);
string endRange = string.Format("{0}{1}", colsUsedAsAlpha, rowsUsed);
Range sourceData = _xlBook.Worksheets["PivotData"].Range[string.Format("A2:{0}", endRange)];
// This is blowing up for some reason, so look for more detail on why
string currentDesc = string.Empty;
try
{
for (int i = 1; i <= rowsUsed; i++)
{
var dynamicCell = (Range)sourceData.Cells[i, DESCRIPTION_COL_NUM];
currentDesc = dynamicCell.Value2.ToString();
if (currentDesc.Equals(desc))
{
var dynamicContractCell = (Range)sourceData.Cells[i, CONTRACT_COL_NUM];
contractVal = (bool)dynamicContractCell.Value2;
break;
}
}
return contractVal;
}
catch (Exception ex)
{
MessageBox.Show(string.Format("currentDesc is {0}; exception is {1}", currentDesc, ex.Message));
}
return false;
}
更奇怪的是,我在特定情况下着色的 rows/cols 范围有一个 "hole cut out of it" 没有着色。
这里是有问题的源数据(中间行(156),最后一列的"TRUE"值是关键):
以下是数据在数据透视表上的呈现方式(中间数据块,第 293-297 行,是关键):
这是我用来透视源数据的代码:
private void AddPivotTable()
{
int FIRST_DESCRIPTION_ROW = 8;
int LINES_BETWEEN_DESCRIPTION_VALS = 5;
var pch = _xlBook.PivotCaches();
int rowsUsed = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
int colsUsed
_xlBook.Worksheets["PivotData"].UsedRange.Columns.Count;
string colsUsedAsAlpha
ReportRunnerConstsAndUtils.GetExcelColumnName(colsUsed);
string endRange = string.Format("{0}{1}", colsUsedAsAlph
rowsUsed);
Range sourceData
_xlBook.Worksheets["PivotData"].Range[string.Format("A1:{0}", endRange)];
PivotCache pc = pch.Create(XlPivotTableSourceType.xlDatabas
sourceData);
PivotTable pvt = pc.CreatePivotTable(_xlPivotTableSheet.Range["A6"
"PivotTable");
pvt.MergeLabels = true;
pvt.PivotFields("Description").Orientation
XlPivotFieldOrientation.xlRowField;
var monthField = pvt.PivotFields("MonthYr");
monthField.Orientation = XlPivotFieldOrientation.xlColumnField;
monthField.NumberFormat = "mmm yyyy";
monthField.DataRange.Interior.Color
ColorTranslator.ToOle(Color.LightBlue);
pvt.CompactLayoutColumnHeader = "Months";
pvt.CompactLayoutRowHeader = "Description";
pvt.AddDataField(pvt.PivotFields("TotalQty"), "Total Packages
XlConsolidationFunction.xlSum).NumberFormat = "###,##0";
pvt.AddDataField(pvt.PivotFields("TotalSales"), "Total Purchases
XlConsolidationFunction.xlSum).NumberFormat = "$#,##0";
PivotField avg = pvt.CalculatedFields().Add("Average Price
"=TotalSales/TotalQty", true);
avg.Orientation = XlPivotFieldOrientation.xlDataField;
// TODO: This calculation needs to change (it needs to actually
made a calculation, rather than just the TotalSales val)
pvt.CalculatedFields()._Add("PercentOfTotal", "=TotalSales");
pvt.AddDataField(pvt.PivotFields("PercentOfTotal"), "% of Total
Type.Missing).NumberFormat = "###.##";
. . .
...这是为相关项目着色的代码:
for (m = 1; m <= dataCnt + 1; m++)
{
string descVal = cellRng.Value2.ToString();
bool isContractItem = GetContractForDescription(descVal);
if (isContractItem)
{
mcellRng = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[rowcnt, 1],
_xlPivotTableSheet.Cells[rowcnt + 4, _grandTotalsColumn-1]];
mcellRng.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
mcellRng.EntireRow.RowHeight = 15;
}
. . .
我不明白着色代码(正上方)如何只能部分工作 - 如第二个屏幕截图所示,B 列中的前几个单元格是白色而不是黄色,其余的范围是。就好像有 此数据中的某些东西 "poison" 阻止了它被着色。
如果我生成较少的列(通过使用与 运行 报告不同的日期范围)它 运行 没有错误信息(但仍然有 "hole" 在范围内有问题)。
如果我只生成两个月就好了;但是如果我尝试六次(在任何一种情况下都存在 "problem" 记录),则会抛出异常...?!?
更新
当我注释掉整个 while 循环时,它 运行 没有错误,但是当然我没有将 ContractItems 着色。
有问题的 while 循环是:
while ((cellRng.Value2 != null) && cellRng.Value2.ToString() != "Total Total Packages")
{
cellRng.RowHeight = 25;
for (m = 1; m <= pivotTableRowCount; m++)
{
string descVal = cellRng.Value2.ToString();
bool isContractItem = GetContractForDescription(descVal);
if (isContractItem)
{
mcellRng = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[rowCounter, 1],
_xlPivotTableSheet.Cells[rowCounter + 4, _grandTotalsColumn - 1]];
mcellRng.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
mcellRng.EntireRow.RowHeight = 15;
}
rowCounter = rowCounter + LINES_BETWEEN_DESCRIPTION_VALS;
cellRng = (Range)_xlPivotTableSheet.Cells[rowCounter, 1];
}
}
这里的什么可能导致错误信息?
导致问题的不是 GetContractForDescription() 方法,因为像这样忽略它:
bool isContractItem = false; //GetContractForDescription(descVal);
...不会阻止错误消息。
更新 2
因为我的头在墙纸上撞了这么久,所以我决定 "go back to the coding board" 重新开始。我现在有这个代码来确定哪些项目是签约的:
List<String> contractItemDescs = GetContractItemDescriptions();
MessageBox.Show(contractItemDescs.Count.ToString());
. . .
private List<string> GetContractItemDescriptions()
{
int FIRST_PIVOTDATA_DATA_ROW = 2;
int DESCRIPTION_COLUMN = 2;
int CONTRACT_COLUMN = 7;
List<string> descriptionsOfContractedItems = new List<string>();
int pivotDataRowCount = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
// Loop through the data sheet, adding the Descriptions for all Contract Items to the generic list
for (int i = FIRST_PIVOTDATA_DATA_ROW; i <= pivotDataRowCount; i++)
{
Range contractItemCell = _xlPivotDataSheet.Cells[i, CONTRACT_COLUMN];
//if (contractItemCell.Value2.ToString() == "TRUE") <= seems to be the same logic as below, but this doesn't work, whereas the below code does...?!?
if (contractItemCell.Value2.ToString().ToUpper() != "FALSE")
{
Range descriptionCell = _xlPivotDataSheet.Cells[i, DESCRIPTION_COLUMN];
String desc = descriptionCell.Value2.ToString();
descriptionsOfContractedItems.Add(desc);
}
}
return descriptionsOfContractedItems;
}
这工作正常 - 消息框显示有效计数。但是请注意,注释掉的 "if" 语句。使用它,我什么也没有添加到列表中;使用我现在使用的看似类似的东西,我得到了 correct/expected 行为,但我不知道为什么。
我不太清楚为什么之前的代码不起作用,但我的猜测是逻辑通常过于混乱。我重构并简化了它(而不是尝试改编其他人编写的一些现有代码,我重新开始并做到了 "my way"),它现在工作得很好。新代码是:
private static readonly Color CONTRACT_ITEM_COLOR = Color.FromArgb(255, 255, 204);
. . .
private void AddPivotTable()
{
. . .
List<String> contractItemDescs = GetContractItemDescriptions();
ColorizeContractItemBlocks(contractItemDescs);
. . .
}
private List<string> GetContractItemDescriptions()
{
int FIRST_PIVOTDATA_DATA_ROW = 2;
int DESCRIPTION_COLUMN = 2;
int CONTRACT_COLUMN = 7;
List<string> descriptionsOfContractedItems = new List<string>();
int pivotDataRowCount = _xlBook.Worksheets["PivotData"].UsedRange.Rows.Count;
// Loop through the data sheet, adding the Descriptions for all Contract Items to the generic list
for (int i = FIRST_PIVOTDATA_DATA_ROW; i <= pivotDataRowCount; i++)
{
Range contractItemCell = _xlPivotDataSheet.Cells[i, CONTRACT_COLUMN];
if (contractItemCell.Value2.ToString().ToUpper() != "FALSE")
{
Range descriptionCell = _xlPivotDataSheet.Cells[i, DESCRIPTION_COLUMN];
String desc = descriptionCell.Value2.ToString();
descriptionsOfContractedItems.Add(desc);
}
}
return descriptionsOfContractedItems;
}
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 8;
int DESCRIPTION_COL = 1;
int ROWS_BETWEEN_DESCRIPTIONS = 5;
int rowsUsed = _xlBook.Worksheets["PivotTable"].UsedRange.Rows.Count;
int colsUsed = _xlBook.Worksheets["PivotTable"].UsedRange.Columns.Count;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
while (currentRowBeingExamined < rowsUsed)
{
Range descriptionCell = _xlPivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value2.ToString();
if (contractItemDescs.Contains(desc))
{
Range rangeToColorize = _xlPivotTableSheet.Range[
_xlPivotTableSheet.Cells[currentRowBeingExamined, 1],
_xlPivotTableSheet.Cells[currentRowBeingExamined + 4, colsUsed]];
rangeToColorize.Interior.Color = ColorTranslator.ToOle(CONTRACT_ITEM_COLOR);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}