Excel公式适用于所有工作表相同的全部列

这个问题可以看成是几个小问题,但主要目标是唯一的。

TL; DR;

我希望在表N中应用excel公式,在考虑所有相应列的情况下,在所有其他表中使用完整公式,同时对所有列应用相同的条件。

细节 :

我的电子表格是一个非常简单和基本的费用会计,它有许多年份和date命名为2015.06等。第一行始终是标题(时间,date,金额,项目,类别等),列总是相应的(例如,在所有表中,列H将是类别, D将是数量)

起始公式是:

  =SUMIF('2015.07'.H2:H67;C20;'2015.07'.D2:D67) // C20 is only a search condition like "travel", or "F&B" 

它在这个简化的手动模式下工作,但是由于我们有电脑,而且我有一个程序员MO,所以我想自动化一下,因此我的问题是:

1 – 如何将此公式应用于所有工作表,即使稍后添加/删除了某些工作表,例如相当于“工作表通配符”

  =SUMIF('*'.H2:H67;C20;'*'.D2:D67) // all sheets 

要么

 =SUMIF('2015*'.H2:H67;C20;'2015*'.D2:D67) // all year 

2 – 由于列的长度不一样,应用手动范围似乎很愚蠢,所以我试了一下

  =SUMIF('2015.07'.H:H;C20;'2015.07'.D:D) 

但它给了我几个不同的错误。

3 – 我可以理解的错误之一,那就是第一行TITLE不是一个数字,所以我试了一下

 =SUMIF('2015.07'.H1:H67;C20;ISNUMBER('2015.07'.D1:D99) )// err 504 

也试过了

 =SUMIF('2015.07'.H1:H67;C20;IF(ISNUMBER('2015.07'.D1:D99) ))// err 509 

 =SUMIF('2015.07'.H1:H67;C20;sum(IF(ISNUMBER('2015.07'.D1:D99)) ))// err 508 

现在,我知道我可以采取简单的工作起始公式,把它放在每一个页面,select无标题的确切范围,然后在最后的夏季页面引用所有其他 – 但严重的是,我也可以使用ABACUS ,这并不是为什么像excel这样的工具被发明出来。 还是我假设这个工具太多了? 这是原始的吗? 我以某种方式拒绝相信,只是责备自己不知道,我应该。

我也知道我可以编写一个VBAmacros,但是在这一点上,花费更less的精力和时间让一些PHP excel库编写一些PHP代码行,将所有的SQL转储并且正确地执行。 但是,再次 – 这是我的错(可能)或Excel的?

PS>。 使用OpenOffice Calc如果有问题的话,还可以在excel中更改语法和不同的错误代码。

编辑我 – 解决scheme

看完@Axel Richards的回答后,即使这并不能帮助我解决问题,但确实帮助我find了方法。

首先,我发现我所遇到的错误是由于自己的名单。 显然,像2005.07 (一个点)这样的名字会给出err 5012005-07 (连字符)会给出err 502 。 这让我明白,我以前的一些尝试其实是对的 – 但命名scheme造成了错误。

所以最终的公式,这对我来说是有效的。 请注意,这是一个数组公式,因此需要用CTRL+SHIFT+ENTER ,而不仅仅是ENTER ,这会产生大括号(我以前不知道)

 {=SUMIF((INDIRECT("20150"&COLUMN(C$1:I$1)&".H"&ROW(A$1:A$500)));$J16;INDIRECT("20150"&COLUMN(C$1:I$1)&".D"&ROW(A$1:A$500)))} 

没有通配符的事实只有一半是正确的,因为解决scheme是定义一个开始时间段和结束时间段,公式会计算所有中间的表单。 这是我的目的的某种通配符。

像这样:

 {=SUMIF((INDIRECT("start"&".H"&ROW(A$1:A$500)));$J16;INDIRECT("END"&".D"&ROW(A$1:A$500)))} 

COLUMN(C$1:I$1)的使用实际上是创build一个数组(3-9),行ROW(A$1:A$500)告诉你公式考虑500行的所有内容。

这不是一个灵活或优雅的解决scheme,但它的工作原理。

我会尝试回答你的问题。

  1. 表通配符

这不可能。 为什么? 因为'2015.07'.H2:H67的表单名称不仅仅是一个string,而是一个参考。 如果在“任何”中将工作表名称从“2015.07”更改,则所有引用该工作表的公式中的所有参考都将更改。

  1. 引用整列和/或整行

这在Openoffice(Libreoffice)中是不可能的。 在Excel =SUMIF('2015.07'!H:H,C20,'2015.07'!D:D)将工作。 在OpenOffice中,我们必须引用第一个单元格和最后一个单元格=SUMIF($H$1:$H$1048576,C20,$D$1:$D$1048576)

顺便说一句:如果您尝试错误=SUMIF('2015.07'.H:H;C20;'2015.07'.D:D)在OpenOffice应该是#NAME? 因为H和D没有定义的名字。 这与成为不是数字无关。 除了那里的错误值之外, SUMIF可以在其总和范围内处理非数字内容。

  1. 错误代码的含义

https://help.libreoffice.org/Calc/Error_Codes_in_Calc

所以我会做什么:

假设下面的例子(在我的Libreoffice中是逗号公式参数分隔符):

在这里输入图像说明

正如你看到K2的公式一样

 =SUMIF($H$1:$H$1048576,$J2,$D$1:$D$1048576) 

J2的公式是

 =$'Sheet N'.$C$20 

这是对“单张N”单元格C20的引用。

Sheet N看起来像:

在这里输入图像说明

D20的公式是

 =SUM(Begin.K2:End.K2) 

这是一个3D参考。 从表格“开始”到表格“结束”的所有表格中的所有单元格K2将被求和。

表“开始”和“结束”只是空的表。

现在您可以随意复制工作表“2015.01”,并将工作表放置在工作表“开始”和“结束”之间。 您可以根据新的月份更改复印的纸张的内容。 只要在所有副本中J2是对=$'Sheet N'.$C20的引用, K2SUMIF公式,则“Sheet N”中的D20将是所有那些将依赖于C20 SUMIF的总和在“表N”中。

但最后要提到的是:

我也知道我可以编写一个VBAmacros,但是在这一点上,花费更less的精力和时间让一些PHP excel库编写一些PHP代码行,将所有的SQL转储并且正确地执行。

你对SQL的暗示是正确的。 但是在SQL中,你也不会每个月都有一个自己的表,然后把所有这些表的UNION 。 你将所有的费用在一个表中作为一个字段来计算。 如果在电子表格中也是这样,那么SUMIF将会很容易,不是吗?

对于macros观问题:

不,因为PHP只能将一个long =SUMIF...+SUMIF...+SUMIF...公式放到一个单元格中。 用VBA或Starbasic你可以有一个UDF(用户定义的function)。 这更加灵活。

示例OpenOffice Libreoffice

 Public Function SUMIFOS(sSheetName as String, lColSearch as Long, vSearchValue as Variant, lColSum as Long) as Variant oDoc = Thiscomponent sFormula = "" vResult = 0 oTextSearch = CreateUnoService("com.sun.star.util.TextSearch") oOptions = CreateUnoStruct("com.sun.star.util.SearchOptions") oOptions.algorithmType = com.sun.star.util.SearchAlgorithms.REGEXP oOptions.searchString = sSheetName oTextSearch.setOptions(oOptions) For Each oSheet in oDoc.Sheets oFound = oTextSearch.searchForward(oSheet.Name, 0, Len(oSheet.Name)) If oFound.subRegExpressions <> 0 then sPath = ThisComponent.URL sSearchColumn = oSheet.Columns(lColSearch-1).AbsoluteName sSumColumn = oSheet.Columns(lColSum-1).AbsoluteName sSearchColumn = "'" & sPath & "'#" & sSearchColumn sSumColumn = "'" & sPath & "'#" & sSumColumn sFormula = "=SUMIF(" & sSearchColumn & ";""" & vSearchValue & """;" & sSumColumn & ")" oDocTMP = CreateUnoService("com.sun.star.sheet.SpreadsheetDocument") oSheetTMP = oDocTMP.createInstance("com.sun.star.sheet.Spreadsheet") oDocTMP.Sheets.insertByName("MySheet", oSheetTMP) oRangeTMP = oSheetTMP.getCellRangeByName("A1") oRangeTMP.Formula = sFormula vResult = vResult + oRangeTMP.Value oDocTMP = Nothing oSheetTMP = Nothing oRangeTMP = Nothing End If Next SUMIFOS = vResult End Function 

示例VBA

 Public Function SUMIFOS(sSheetName As String, lColSearch As Long, vSearchValue As Variant, lColSum As Long) As Variant Set oWB = ThisWorkbook vResult = 0 Set oRegExp = CreateObject("vbscript.regexp") oRegExp.Pattern = sSheetName For Each oSheet In oWB.Sheets If oRegExp.test(oSheet.Name) Then Set rSearchColumn = oSheet.Columns(lColSearch) Set rSumColumn = oSheet.Columns(lColSum) vResult = vResult + WorksheetFunction.SumIf(rSearchColumn, vSearchValue, rSumColumn) End If Next SUMIFOS = vResult End Function 

作为公式的用法:

 =SUMIFOS("2015.0[1,4]",8,C20,4) 

如果第8列中的名称与第C20列中的“2015.0 [1,4]”匹配,则包含C20的值。

给这个代码一个镜头:

 Sub CreateSumIfFormulaForAllSheets() Tmp = "" For i = 1 To Sheets.Count Tmp = Tmp & IIf(Tmp = "", "=SUMIF('" & Sheets(i).Name & "'!H:H,C20,D:D)", "+SUMIF('" & Sheets(i).Name & "'!H:H,C20,D:D)") Next i Range("A1").Formula = Tmp End Sub 

假设您试图在所有工作表中的C列在H列的所有工作表上的D列中获取所有值的单个总和,则这将起作用。 只要将“A1”更改为公式通常所在的单元格。除非列D中有错误值,否则不必担心ISNUMBER,因为SUMIF忽略了文本。

如果实际上需要定义这些列的范围(如H2:H67),而不是只查看整列,则需要指定用什么标准进行确定,然后才能将其编码到此macros中。 你确实说过“整列”,这一定会看整列。