在我的VSTO外接程序项目中,如果我选择一个空单元格(例如F11),并在该范围内运行find以获取任何值,则似乎会搜索整个工作表并在期望范围内返回范围A1:E10返回null。下面是我选择的单元格的图像。
我正在通过选择来访问此范围,当我在调试时进行检查时,选择的列为6列,行为11列。当我尝试在此范围内找到任何东西时,我希望得到一个空值,但我却得到了E10的值,这没有任何意义。
这是我的C#代码,第一部分得到选择并遍历 范围区域,如果选择一个区域,则只有1个区域。
即使F11是唯一选择的单元格,结尾处val1和val2的值也都是3197077000。
<add namespace="HtmlHelpers.BeginCollectionItem" />
当我在VBA中执行相同的操作时,按预期在F11上运行find时会得到一个空值
using Microsoft.Office.Interop.Excel;
using System;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelAddIn1
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
Excel.Range selection = Globals.ThisAddIn.Application.Selection;
if (null != selection)
{
var sheet = selection.Worksheet;
var book = (Excel.Workbook)sheet.Parent;
var areasCount = selection.Areas.Count;
for (int i = 1; i <= areasCount; i++)
{
var area = selection.Areas[i];
var test = area.Value;
var testCount = area.Count;
var testRow = area.Row;
var testCol = area.Column;
Excel.Range lastCellInLastRow = area.Find(
"*",
Type.Missing,
XlFindLookIn.xlFormulas,
XlLookAt.xlPart,
XlSearchOrder.xlByRows,
XlSearchDirection.xlPrevious,
false,
Type.Missing,
Type.Missing);
Excel.Range lastCellInLastCol = area.Find(
"*",
Type.Missing,
XlFindLookIn.xlFormulas,
XlLookAt.xlPart,
XlSearchOrder.xlByColumns,
XlSearchDirection.xlPrevious,
false,
Type.Missing,
Type.Missing);
var val1 = lastCellInLastCol.Value;
var val2 = lastCellInLastRow.Value;
}
}
}
}
}
答案 0 :(得分:0)
简短答案:互操作/范围。查找可能不可靠。尽可能少使用Interop。
更长的答案:我在实践中注意到的关于Range.Find
的不可靠的事情之一是,它似乎记忆了以前搜索过的内容。这可能是问题,也可能不是问题,但是如果我是您,我不会费心尝试解决问题,因为您可以按以下方式解决您的问题:
C#
正则表达式库并嵌套循环以搜索数组需要做更多的工作,但是值得摆脱不可靠的Interop基础。以下是一些入门方面的小代码:
public string[,] ReadValues(Range range)
{
return ConvertToStringArray2D(GetArray(range, () => range.Value2));
}
private string[,] ConvertToStringArray2D(Array values)
{
string[,] retArray = new string[values.GetLength(0), values.GetLength(1)];
// loop through the 2-D System.Array and populate the 1-D String Array
for (int row = 1; row <= values.GetLength(0); row++)
{
for (int col = 1; col <= values.GetLength(1); col++)
{
if (values.GetValue(row, col) == null)
{
retArray[row - 1, col - 1] = "";
}
else
{
retArray[row - 1, col - 1] = values.GetValue(row, col).ToString();
}
}
}
return retArray;
}
private Array OneBasedSingletonArray2D()
{
return Array.CreateInstance(typeof(Object), new int[] { 1, 1 }, new int[] { 1, 1 });
}
private Array GetArray(Range range, Func<object> dataProducer)
{
if (range.Cells.Count == 0)
{
return Array.CreateInstance(typeof(Object), 0, 0);
}
if (range.Cells.Count == 1)
{
//Creating a 1-based array to fit with Excel's 1-based indexing
Array retArray = OneBasedSingletonArray2D();
retArray.SetValue(dataProducer.Invoke(), 1, 1);
return retArray;
}
else
{
return (Array)dataProducer.Invoke();
}
}