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这样的工具被发明出来。 还是我假设这个工具太多了? 这是原始的吗? 我以某种方式拒绝相信,只是责备自己不知道,我应该。
我也知道我可以编写一个VBA
macros,但是在这一点上,花费更less的精力和时间让一些PHP excel库编写一些PHP代码行,将所有的SQL转储并且正确地执行。 但是,再次 – 这是我的错(可能)或Excel的?
PS>。 使用OpenOffice Calc如果有问题的话,还可以在excel中更改语法和不同的错误代码。
编辑我 – 解决scheme
看完@Axel Richards的回答后,即使这并不能帮助我解决问题,但确实帮助我find了方法。
首先,我发现我所遇到的错误是由于自己的名单。 显然,像2005.07
(一个点)这样的名字会给出err 501
和2005-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,但它的工作原理。
我会尝试回答你的问题。
- 表通配符
这不可能。 为什么? 因为'2015.07'.H2:H67
的表单名称不仅仅是一个string,而是一个参考。 如果在“任何”中将工作表名称从“2015.07”更改,则所有引用该工作表的公式中的所有参考都将更改。
- 引用整列和/或整行
这在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
可以在其总和范围内处理非数字内容。
- 错误代码的含义
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
的引用, K2
是SUMIF
公式,则“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中。 你确实说过“整列”,这一定会看整列。