Excel VBA:如何检查计算列?

无论如何检查VBA是否Excel中的一个表(ListObject)的特定列是一个计算列(如在http://office.microsoft.com/en-us/excel-help/use-calculated-columns- in-an-excel-table-HA010342380.aspx )?

请注意,计算的列不仅将为每行设置相同的R1C1公式集,还将在添加新行时自动展开(如果删除整个数据体范围,然后重新创build一些新行,它甚至会重新填充)。 因此检查具有一致公式的列与检查计算公式不同。

甚至可以计算一列,但是可以用其他公式或值覆盖其中一行,并使自动扩展function保持不变。

所以我相当确信这是列的一些属性,我只是不知道在哪里可以通过VBA访问它。 如果它没有通过VBA对象模型暴露出来,是否有一些workarround来获得这个信息?

在此先感谢,卡洛斯

编辑:我做了一些挖掘Excel Office打开XML文件,事实certificate,我正在寻找的是<tableColumn> xl \ tables \ table * .xml文件的<tableColumn>定义的元素。 有没有办法通过VBA来实现?

编辑2:这是一个与我可以想出testing用例的示例文件 。 VBA应该表示第1,2和3列是计算列,第4列和第5列不是。

这一个给你的例子适当的答案。

不幸的是,根据自己的情况,它有一些潜在的致命缺点。 首先,它会导致重新计算,因此样本中通过=RAND()公式生成的随机数被更改。

第二个缺点是它修改工作表以获得答案(它删除了它所做的修改,但仍然被修改)。 我可以想到一些仅有部分有用的解决方法:(a)尽可能less地执行此操作并caching所有列的结果;(b)将表复制到新的工作簿并运行例程(并删除新的工作簿) 。 虽然后者将避免修改缺陷,但仍会触发原始工作簿的重新计算(否则有其自身的缺点)。 除此之外,除非复制整个范围(不仅仅是头文件),否则将表复制到一个新的工作簿会丢失表/ L​​istObject。 那么它也似乎促进了第四列(非计算一致的公式)是一个计算的。 不幸的是,这个提升也发生在拷贝整个表格时。

那么,FWIW:

 Sub TestTable() Dim ans As String Let ans = "" Dim li As ListObject Set li = ActiveSheet.ListObjects(1) Dim rowCountBefore As Long Let rowCountBefore = li.ListRows.Count Dim lr As ListRow Set lr = Nothing On Error Resume Next Set lr = li.ListRows.Add(AlwaysInsert:=True) On Error GoTo 0 Dim rowCountAfter As Long Let rowCountAfter = li.ListRows.Count If Not (lr Is Nothing) And rowCountAfter = rowCountBefore + 1 Then Dim c As Long For c = 1 To li.DataBodyRange.Columns.Count Dim b As Boolean Let b = lr.Range.Cells(1, c).HasFormula ans = ans & "col " & c & ": " & b & "; " Next li.ListRows(rowCountAfter).Delete End If MsgBox ans End Sub 

以前没有看过,但它似乎是ListObject的列范围的属性,如下所示:

 Dim wks As Worksheet Set wks = ActiveSheet Dim li As ListObject Set li = wks.ListObjects(1) Dim col As ListColumn Set col = li.ListColumns(2) ' assuming column 2 of the table has a calculated formula Dim r As Range Set r = col.DataBodyRange Let b = Not IsNull(r.FormulaArray) if b then Let b = Len(r.FormulaArray) > 0 ' case where r.FormulaArray = "", suspect it's not a calculated column End If MsgBox b 

如果IsNull(r.FormulaArray)那么它没有一个计算列,否则就是这样。

心连心


好了,玩了这一点,我看到的是,使用上面得到的范围对象是不同的任何给定单元格的范围对象,所以如果你有一个给定的单元格,我想你将需要获得相应的ListColumn的范围通过.DataBodyRange。

(例如,如果在上面插入Set r = r.Cells(1,1) ,那么IsNull(r.FormulaArray)testing不再用于testing计算列,而只是说如果范围有一个公式,但可以计算或不计算)。

此外,虽然r.FormulaArray似乎是计算列时的string,如果不是(计算列),那么.FormulaArray会产生null,这不是一个有效的string值(使它很难在为了捕获你必须使用的variables不是一个布尔值); 我发现IsNull(r.FormulaArray)似乎工作正常。


如果我在已经计算的列的右侧添加一列,那么r.FormulaArray =“”为新添加的列。 如果您将某个值放入其中一个单元格中,那么公式数组将立即恢复为更为期望的NULL值。 所以,我添加了一个testing,我认为这是误报。