简体   繁体   English

Excel.Interop的Worksheet.UsedRange属性中可能存在错误?

[英]Possible bug in Excel.Interop's Worksheet.UsedRange property?

Take a gander at the following code. 仔细阅读以下代码。 Basically, this is a function that gets called in order to identify the used range of a worksheet, loop through that range, and hash social security numbers. 基本上,调用此函数是为了识别工作表的使用范围,遍历该范围并哈希社会安全号。

Here's the problem. 这是问题所在。 If I create a spreadsheet and populate one cell, the function does not hash that cell. 如果创建电子表格并填充一个单元格,则该函数不会对该单元格进行哈希处理。 However, if I populate more than one, it works. 但是,如果我填充一个以上,它将起作用。

Could this be a bug in the UsedRange property? 这可能是UsedRange属性中的错误吗? Or am I missing something? 还是我错过了什么?

thanks much. 非常感谢。

Woody 伍迪

try
{
    foreach (Excel.Worksheet ws in _excelWorksheet)
    {
        // Grab the range of numbers that populates the XLS.
        Excel.Range range = ws.UsedRange;
        // In the following cases, Value2 returns different types:
        //
        // 1. The range variable points to a single cell:
        // Value2 returns a object
        //
        // 2. The range variable points to many cells:
        // Value2 returns object[,]

        object[,] values = (object[,])range.Value2;

        for (int row = 1; row <= values.GetUpperBound(0); row++)
            for (int col = 1; col <= values.GetUpperBound(1); col++)
            {
                // Convert values to strings.
                string value = Convert.ToString(values[row, col]);

                // Mask the value that we retrieved and store it in a variable.
                switch (_mdOptions.cbobxEncryption.Text)
                {
                    case "MD5":
                    {
                        replaceSSN = SHA2Hash.ComputeHash(value, "MD5", null);
                        break;
                    }
                    case "SHA256":
                    {
                        replaceSSN = SHA2Hash.ComputeHash(value, "SHA256", null);
                        break;
                    }
                    default:
                    {
                        replaceSSN = SHA2Hash.ComputeHash(value, "SHA256", null);
                        break;
                    }
                }    

                // Match expressions to sensitive data and replace with the hash
                // value.
                if (Regex.IsMatch(value, @"\b[0-9]{3}-[0-9]{2}-[0-9]{4}\b"))
                {
                    range.Cells.set_Item(row, col, replaceSSN);
                }
                else if (Regex.IsMatch(value, @"\b[0-9]{3}[0-9]{2}[0-9]{4}\b"))
                {
                    range.Cells.set_Item(row, col, replaceSSN);
                }
            }
        }
    }
    catch (Exception)
    {
        // This is here because of a non-fatal error that we're getting with
        // Windows 7 during the hashing phase. Everything still works,
        // it's just that this error keeps popping up.

        // REVIEW FOR WINDOWS 7 COMPATABILITY
        ;

        //MessageBox.Show("There was a major error. Please restart the program.");
        //MessageBox.Show(@"Exception: " + ee);
    }


    // Pull the hashed password from the registry and add it to the SaveAs
    //string saveAsPassword = Convert.ToString(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Mask Data", "Password", ""));
    /*
    _excelWorkbook.SaveAs("Results.xls",
    Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, false,
    Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
    Type.Missing, true, Type.Missing,
    Type.Missing, Type.Missing); 
     */
     // Report success.    
    MessageBox.Show("File masked successfully.", 
        "Mask Data", MessageBoxButtons.OK, MessageBoxIcon.Information,
        MessageBoxDefaultButton.Button1, 
        MessageBoxOptions.DefaultDesktopOnly);
    // Shutdown instance of Excel.
    //_excelApp.Quit();

    // Release memory.
    GC.Collect();
    GC.WaitForPendingFinalizers();
    Marshal.ReleaseComObject(_excelWorkbook);
    Marshal.ReleaseComObject(_excelApp);         
}

You can't convert a double to a 2 dimensional array of objects, if only because a double has only 1 dimension. 您不能将一个double转换为2维的对象数组,仅是因为double只有1维。 Apologies if I am telling you something you already know but the term 'double' means double precision, and has nothing to do with 2 dimensional arrays (as defined by object[,]). 抱歉,如果我告诉您您已经知道的内容,但术语“双精度”表示双精度,与二维数组(由object [,]定义)无关。

You could simply add a check for this case so the first few lines would look like: 您可以为此情况添加一个检查,因此前几行如下所示:

XLS.Excel.Range range = ws.UsedRange;
object[,] values;
if (range.Value2.GetType().IsArray)
{
    values = (object[,])range.Value2;
}
else
{
    values = new object[2,2];
    values[1,1] = range.Value2;
}

I don't have VS on this machine so the code is untested but should be pretty close 我在这台机器上没有VS,因此代码未经测试,但应该非常接近

EDIT: Having knocked up a quick test app I can see what UsedRange.Value2 is doing - it returns an array of all of the sheet values which is why if there is more than 1 cell it is an array however for one cell it will just return that value (which could be any type). 编辑:敲了一个快速测试应用程序,我可以看到UsedRange.Value2在做什么-它返回所有工作表值的数组,这就是为什么如果有多个单元格,则它是一个数组,但是对于一个单元格,它将只是返回该值(可以是任何类型)。 The code above will work however is a bit of a hack. 上面的代码可以工作,但是有点麻烦。 The correct way to get the number of rows and columns is using: 获取行数和列数的正确方法是使用:

range.Rows.Count

and

range.Columns.Count

If you change your for loops to use these 2 values rather than the array bounds it will solve your problem, and will work for both single and multiple rows 如果将for循环更改为使用这2个值而不是数组边界,则它将解决您的问题,并且适用于单行和多行

如代码注释中所述,Value2属性为单个单元格返回单个文本/数字/逻辑/错误值,或为多个单元格返回object [,]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM