如何以编程方式创建Excel“排序/筛选组合框”?

时间:2015-11-04 19:02:25

标签: c# excel office-interop excel-interop

我正在对手动创建的电子表格进行逆向工程以进行动态创建。大多数单元格都填充了简单的数据,但有一些是“排序/过滤”下拉列表,如下所示:

enter image description here

如何动态创建这样的控件?

有没有办法在Excel电子表格中“查看源代码”,看看生成这些控件可能需要哪种代码?

更新

调整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; 

......但是它崩溃了,向我展示了这个注目的笔记:

enter image description here

我怎么误入歧途?

更新2

要在下面的评论中回答MacroMarc,下面是遗留/模型电子表格中的过滤器控件的屏幕截图(我正在进行逆向工程):

enter image description here

在这种情况下,我从列表中取消选择“11月”,以便将其删除,如您所见。因此,用户选择的内容会影响下面列的可见性。

更新3

由于所有这些花哨的东西都被遗留在遗留电子表格中,我现在正在考虑将其保存为模板,并根据需要简单地替换单元格内容。有什么理由说这不可行吗?

如果没有,为了实现这一点,我应该保存现有的spreadhseet“As Excel Macro-Enabled Workbook”吗?

更新4

我尝试过调整MacroMarc的答案:

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;

...但得到了运行时异常:

enter image description here

是否导致问题的最后一行(将rangeFilter指定给范围的Value属性)?如果是这样, 我应该将monthFilter分配给什么,或者我应该用它做什么?

2 个答案:

答案 0 :(得分:2)

不,你不能"查看来源"在Excel电子表格上。但是,您可以打开VBA编辑器并查看已写入的代码。在现代版本的Excel中,如何做到这一点可能并不那么明显。在Excel窗口的顶部,查找小箭头,单击它,然后会出现一个下拉列表。

enter image description here

在列表的底部,您将看到一个标题为"更多命令"的选项。单击此处,将打开以下窗口。

enter image description here

然后,您可以过滤命令列表。选择"开发人员标签"在右侧,您将看到一个名为" Visual Basic"的命令。您还有其他用于录制宏的命令,因此请添加整个列表。从我的第一个屏幕截图中可以看出,我已经在我的Excel副本中添加了这些。

请注意,您可能还需要调整安全设置。

既然你知道如何打开VBA编辑器,并且你有宏命令,你可以查看创建过滤器的代码,或者你可以自己创建一个过滤器并记录一个宏来看看它是如何完成的。生成的宏将在VBA中,您可以根据需要对其进行修改。

首先单击快速访问工具栏图标,然后单击#34;记录宏",然后通过选择要过滤的表格顶行中的单元格添加过滤器,然后单击数据选项卡;点击过滤器。

录制宏后,您应该在VBA编辑器中看到如下内容:

Sub Macro1()
'
' Macro1 Macro
'

'
    Selection.AutoFilter
    ActiveSheet.Range("$A$1:$D$6").AutoFilter Field:=3, Criteria1:="1023123"
    Selection.AutoFilter
End Sub

现在我们已经涵盖了整个"开源"问题,这是互操作问题的解决方案。我已经采取了您的代码,更改了它,并对其进行了测试以重现错误,并发现了问题所在。该过程必须仅选择表格的一部分或电子表格的完全空白区域。当Excel尝试查找要过滤的范围的角时,它会遇到问题,因为找不到可识别的角。以此为例:

    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);

在下面的屏幕截图中,我突出显示了代码尝试放置过滤器的行,它是空的。所以,这里发生的是代码由于某种原因没有引用您正在使用的电子表格的正确区域。

解决此问题的一种方法是引用顶行中的第一个单元格而不是整行。只要表中没有间隙,Excel就会找到整个表。

enter image description here

因此,尝试在此范围内应用AutoFilter而不是整个范围:

_xlSheet.Cells[7, 3]

此外,我应该指出,如果您不知道,但是当您分配" sortFilterCombobox"对于单元格,您实际上是将一个布尔值弹出到单元格中。 AutoFilter函数返回一个布尔值,而不是过滤器对象本身。

答案 1 :(得分:2)

过滤器由Excel表格中的范围本机创建,或者可以通过Excel界面上的“过滤器”按钮创建。正如约书亚所说,你可以尝试在VBA中编写脚本,但似乎你的问题标签是你正在使用C#和Excel-Interop(??)

尝试在C#代码中使用范围对象句柄并应用.Autofilter方法。

object result = (object)oRange.AutoFilter(1, System.Reflection.Missing.Value,ExApp.XlAutoFilterOperator.xlAnd,System.Reflection.Missing.Value, true);

上面的ExApp是Interop.Excel命名空间的别名。

对于Developer选项卡,请查看Google版本上的Google自定义功能区选项。右键单击功能区,或文件 - >选项 - 等

<强>更新

好的,为了修改pivotfield的排序和过滤属性,你需要抓住pivotField的句柄,例如你的'月'和#39;过滤器在单元格D5中,您可以执行以下操作:

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