为什么某些单元格没有发生着色,这与 "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;
    }
}