C# 如何以编程方式创建Excel;排序/筛选组合框“;?
我正在反向工程一个手动创建的电子表格,用于动态创建。大多数单元格都填充了简单的数据,但也有一些是“排序/筛选”下拉列表,如下所示:C# 如何以编程方式创建Excel;排序/筛选组合框“;?,c#,excel,office-interop,excel-interop,C#,Excel,Office Interop,Excel Interop,我正在反向工程一个手动创建的电子表格,用于动态创建。大多数单元格都填充了简单的数据,但也有一些是“排序/筛选”下拉列表,如下所示: var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]]; object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.V
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
如何动态创建这样的控件
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
是否有办法在Excel电子表格中“查看源代码”,以查看生成这些控件可能需要哪种代码
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
更新
改编MacroMark的代码,编译:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
…但它崩溃了,给我带来了这样一个谴责:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
我怎么迷路了
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
更新2
为了回答MacroMarc在下面的评论,这里是遗留/模型电子表格(我是逆向工程)中过滤器控件的屏幕截图:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
在本例中,我从列表中取消选择了“十一月”,因此它被删除,如您所见。因此,用户选择的内容会影响下面列的可见性
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
更新3
在遗留电子表格中加入了所有这些花哨的内容后,我现在考虑将其保存为模板,并根据需要简单地替换单元格内容。有什么理由不可行吗
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
如果没有,要完成此操作,是否应将现有的spreadhseet保存为“启用Excel宏的工作簿”
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
更新4
我试着这样改编马克的回答:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
Range monthYearCells = _xlSheet.Range[_xlSheet.Cells[COLUMN_HEADING_ROW, MONTH1_COL], _xlSheet.Cells[COLUMN_HEADING_ROW, MONTH13_COL]];
object monthFilter = (object)monthYearCells.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
var monthFilterCell = (Range)_xlSheet.Cells[6, 3];
monthFilterCell.Value = monthFilter;
…但得到了运行时异常:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
是不是最后一行(将monthFilter指定给范围的Value属性)导致了问题?如果是这样,我应该将monthFilter分配给什么,或者应该如何处理它?否,您不能在Excel电子表格上“查看源代码”。但是,您可以打开VBA编辑器,查看已写入的代码。在Excel的现代版本中,如何做到这一点可能并不那么明显。在Excel窗口的顶部,查找小箭头,单击它,将出现一个下拉列表
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
在列表的底部,您将看到一个名为“更多命令”的选项。单击此处,将打开以下窗口
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
然后可以过滤命令列表。选择“开发人员选项卡”,您将在右侧看到一个名为“Visual Basic”的命令。您还有其他用于录制宏的命令,因此请添加整个列表。正如您从我的第一个屏幕截图中看到的,我已经在我的Excel副本中添加了这些
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
请注意,您可能还需要调整安全设置
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
现在,您已经知道如何打开VBA编辑器,并且已经有了宏命令,您可以查看创建过滤器的代码,也可以自己创建过滤器并录制宏以查看如何执行。生成的宏将在VBA中,您可以随意修改它
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
首先单击“记录宏”的快速访问工具栏图标,然后通过选择要过滤的表顶行中的单元格添加过滤器,然后单击数据选项卡;单击过滤器
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
录制宏后,应在VBA编辑器中看到如下内容:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
Sub Macro1()
'
' Macro1 Macro
'
'
Selection.AutoFilter
ActiveSheet.Range("$A$1:$D$6").AutoFilter Field:=3, Criteria1:="1023123"
Selection.AutoFilter
End Sub
既然我们已经讨论了整个“开源”问题,下面是互操作问题的解决方案。我已经获取了您的代码,对其进行了更改,并对其进行了测试,以重现错误,并发现了问题所在。该过程必须仅选择表格的一部分或电子表格的一个完全空白区域。当Excel试图查找要筛选的范围的角点时,会遇到问题,因为没有可识别的角点可供查找。以此为例:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
Excel.Application app = new Excel.Application();
app.Visible = true;
Excel.Workbook wk = app.Workbooks.Add();
Excel.Worksheet sh = wk.Sheets[1];
sh.Cells[1, 1] = "col1";
sh.Cells[1, 2] = "col2";
sh.Cells[1, 3] = "col3";
sh.Cells[1, 4] = "col4";
sh.Cells[2, 1] = "data";
sh.Cells[2, 2] = "data";
sh.Cells[2, 3] = "data";
sh.Cells[2, 4] = "data";
sh.Cells[3, 1] = "data2";
sh.Cells[3, 2] = "data2";
sh.Cells[3, 3] = "data2";
sh.Cells[3, 4] = "data2";
//Excel.Range r1 = sh.Range[sh.Cells[1, 1], sh.Cells[3, 4]]; //this works
Excel.Range r2 = sh.Range[sh.Cells[7, 3], sh.Cells[7, 15]]; //this fails
//object sortFilterCombobox1 = (object)r1.AutoFilter(1, System.Reflection.Missing.Value, Excel.XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
object sortFilterCombobox2 = (object)r2.AutoFilter(1, System.Reflection.Missing.Value, Excel.XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
在下面的屏幕截图中,我突出显示了代码试图设置过滤器的行,该行为空。因此,这里发生的事情是,由于某种原因,代码没有引用您正在使用的电子表格的正确区域
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
解决此问题的一种方法是引用顶行中的第一个单元格,而不是整行。只要表格中没有空白,Excel就会找到整个表格
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
因此,请尝试在此范围而不是整个范围内应用自动筛选:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
_xlSheet.Cells[7, 3]
另外,我应该指出,如果您不知道,但是当您将“sortFilterCombobox”分配给一个单元格时,实际上是在单元格中弹出一个布尔值。自动筛选函数返回布尔值,而不是筛选对象本身。筛选是通过Excel表格中的范围或Excel界面上的筛选按钮本地创建的。正如Joshua所说,您可以尝试在VBA中编写脚本,但从您的问题标签来看,您似乎在使用C#和Excel互操作(?)
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
尝试在C代码中使用范围对象句柄并应用.Autofilter方法
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
object result = (object)oRange.AutoFilter(1, System.Reflection.Missing.Value,ExApp.XlAutoFilterOperator.xlAnd,System.Reflection.Missing.Value, true);
其中,上面的ExApp是Interop.Excel命名空间的别名
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
至于开发人员选项卡,请查看google上用于Excel版本的自定义功能区选项。右键单击功能区或文件-->选项--等等
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
更新
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
好的,要修改数据透视字段的排序和筛选属性,您需要抓住数据透视字段的句柄,例如,如果“月”筛选器位于单元格D5中,您可以执行以下操作:
var rangeMonthYears = _xlSheet.Range[_xlSheet.Cells[7, 3], _xlSheet.Cells[7, 15]];
object sortFilterCombobox = (object)rangeMonthYears.AutoFilter(1, System.Reflection.Missing.Value, XlAutoFilterOperator.xlAnd, System.Reflection.Missing.Value, true);
_xlSheet.Cells["6", "C"] = sortFilterCombobox; //MonthLabel;
Range oRange = oSheet.get_Range("D5", "D5");
PivotField pf = oRange.PivotField;
pf.AutoSort((int)XlSortOrder.xlDescending, "Month"); //this sorts in reverse order
pf.PivotItems(2).Visible = false; //this makes the second item deselected in filter
谢谢请参阅更新2。哦,它正在使用互操作。我会调查并更新我的答案。事实上,73…715是我的正确范围;这就是月份标签存在的地方(9月14日、10月14日等)。试着在包含列标签的行中的第一个单元格上进行自动筛选,而不是整行。啊,我明白了。我给你的代码只是在Excel范围内启用“过滤器下拉列表”。它们会自动显示在该范围的顶行。您似乎希望从Excel单元格中捕获一年中的12个月,并将其显示在完全不同的单元格中的下拉列表中。i、 e.您希望传输“过滤器下拉列表”。无法使用该语法/对象。这可能会导致一个又一个问题。也许你最好解释一下你希望实现的目标,我们会尽力给你最好的建议“过滤器下拉列表”是一项功能,可下拉到列的顶部。只需