没有VBA的迭代/循环替换

时间:2018-08-15 15:15:54

标签: excel excel-formula concatenation substitution

简短问题:

如果我有一个串联字符串“ |#|#|#| ... |#|”,我该如何对每个数字应用乘数并更新串联文本?例如,对于| 4 | 12 | 8 |,乘以2并把连接的文本更新为| 8 | 24 | 16 |。

背景

我有三列感兴趣的文章。第一列包含日期,第二列包含日期或金额,第三列将数据连接为“ |#|#| ... |#|”格式(例如| 2 | 5 |,| 2 | 5 | 12 |,| 4 | 12 |等)。有时,需要对连接的数据应用一个乘数,并且相应的数字也需要相应地更新。

一个例子是-

Date        Amt     Concatenated Data
01/01/18    2       |2|
01/05/18    5       |2|5|
02/06/18    12      |2|5|12|
03/25/18    -3      |4|12|
03/31/18    8       |4|12|8|
04/01/18    F2      |8|24|16|  (factor of 2 applied)
04/15/18    12      |8|24|16|12|
04/01/18    F1/4    |2|6|4|3|  (factor of 1/4 applied)

使用公式,如何将因子应用于连接的数据并更新各个数字?

我受以下条件的约束:

  • Excel 2007,因此没有TEXTJOIN函数
  • 没有VBA或UDF(由于安全策略)
  • 个人数字是动态的(即,SUBSTITUTE公式的“ old_text”参数不能使用静态值)
  • 级联数据中单个数字的数量也是动态的(可能包含一个数字,或者可能包含数十个不同的数字)

我可以使用数组公式提取单个数字。我什至可以将这些数字乘以因子以产生数组结果。但是,我无法重建连接的数据,因为CONCATENATE在数组上不起作用。我也尝试过SUBSTITUTE,但是无法遍历“ |”分隔符。我只能替换给定的句段(例如,将“ | 2 |”的所有条目更改为“ | 4 |”)。嵌套SUBSTITUTE或使用单独的列均无效,因为它可能涉及数十个实例。

只需在级联数据上添加一些信息:

  • Amt> 0,然后将值串联到上一个串联值的末尾
  • Amt <0,开始减少连接值(CV)中的单个数字,直到达到减少量为止(例如,对于| 2 | 5 | 12 |且Amt = -3,将CV减小为| 4 | 12 |,即-第一段为2,第二段为-1)
  • Amt减少仅限于前CV的单个数字之和(例如,对于| 4 | 12 |,减少不能超过16)
  • Amt = F#,表示乘数,需要更新CV的数字
  • CV没有最大值(可以有几十到数百个单个数字,数字范围从1到100,000+),除了Excel本身对字符串长度应用的任何最大值之外。

1 个答案:

答案 0 :(得分:0)

高水平

  1. 此解决方案的四个部分
  2. 它们满足先决条件(2007 兼容性、无 VB、无 Office 365 要求、无自定义 VB 函数,提供完整的可变长度单元格的“动态”性质以进行连接)
  3. 警告:据最佳知识/研究,没有简约的单细胞功能,因此建议采取临时步骤)
  4. 另外一个警告:我认为围绕分隔数据包装图形的简单“黑客”是不可能的(请参阅下面的“其他/各种”☺)

第 1-4 部分

下面的第 1-4 部分是与以下屏幕截图相关的功能:

Excel Depiction of Dynamic Concatenation Solution - Excel 2007

我也已上传/修改以满足 Google 表格的要求(请参阅 here) 第 1 部分和第 2 部分:

相似之处在于它们依靠 FilterXML 技术来计算组件/术语,并分别拆分单元格:

第 1 部分:

=COUNT(2*TRANSPOSE(FILTERXML("<AllText><Num>"&SUBSTITUTE(LEFT(MID(D12,2,LEN(D12)-1),LEN(MID(D12,2,LEN(D12)-1))-1),"|","</Num><Num>")&"</Num></AllText>","//Num")))

注意:谷歌表格无法识别 FilterXML,因此相应地修改了技术/功能。例如,上面可以使用第 2 部分中拆分单元的计数来确定(比上面提出的方法更容易/更简单,尽管由于位于拆分单元右侧的任何单元会干扰这种方法的普通功能,因此鲁棒性较差) .

第 2 部分:

它要么是手动方法,要么是一系列花哨的“中”和/或替换/左/右函数,或者是以下 FilterXML 代码,根据各种来源(例如 here)应与 Excel 2007 兼容:

=IF(LEFT(C12,1)="F",1*SUBSTITUTE(C12,"F",""),1)*TRANSPOSE(FILTERXML("<AllText><Num>"&SUBSTITUTE(LEFT(MID(D12,2,LEN(D12)-1),LEN(MID(D12,2,LEN(D12)-1))-1),"|","</Num><Num>")&"</Num></AllText>","//Num"))

可以看出与第 1 部分(重新:FilterXML)的共性 - 唯一的区别是计数(第 1 部分)已被转换(乘法因子,如 O.P 的 Q 中给出)所取代。

第 3 部分

这里没什么特别的 - 一个简单的连接(我知道,这与“递归”替换函数相去甚远,但是嘿 - 它可以解决问题,并且始终可以放置在原始工作表的镜像副本中以避免空间问题/细胞交互问题)

=IF(H12="","",IF(G24="","|","")&G24&H12&"|")

第 4 部分

由于第 1 部分中导出的项数,偏移函数可以轻松确定与“转换”值的连接“构建”相关的最终单元格(根据第 3 部分):

=OFFSET(H31,0,E31-1,1,1)

其他/各种

存在各种其他建议和“变通方法”;不幸的是,这些似乎以一种或另一种方式未能满足规定的先决条件,videlicit:

a) 基于函数/公式 b) 没有 VB c) Excel 2007 d) 动态(可变/未知数量的术语)

  1. 手册:例如function = concatenate(transpose(desired range)),然后是 concatenate 函数的组件,然后按 F9 转换为计算值,这些值很容易适用于 concatenate 函数。缺点:与“自动化解决方案”相关的时间很长(需要为每个适用的玩具完成)。优势:不需要额外的“电子表格空间”,一开始就更快/更直接地实施。
  2. “构建”方法的变体:例如但是,根据第 3 部分的规定,仅凭这一点并不能确保对原始串联列表中数量未知的术语采用自动化方法。
  3. 在之前的解决方案 (here) 中提到过,但在使用早期版本的 Excel 时,您可能有资格使用 Office 365 功能(请参阅 Office Insider here
  4. 其他建议(请注意本论坛的上/下)建议 textjoin(所以不确定这是理解问题还是什么☺)
  5. 是的,正如开头提到的,您可以使用简单的图表轻松实现所需的结果!只是为了好玩,以相反的顺序对数据进行排序,并将拆分/分隔的值包含为条形图的“x 值”(根据 defn。对于这种类型的图,现在将沿着普通的笛卡尔 'y /垂直'轴)...

Graphical solution

对此给予零分,但我认为这是一个有趣的发现! (如果仍然有疑问,如果我不删除除轴标签之外的所有内容,“图表”会是什么样子......):

Funny little graph - probably quickest solution!!

以上相关其他项目的大量参考资料,包括研究领域,如下:

还有一件事......

在真正的哥伦布风格的作案手法中,考虑了其他想法/方法:

  • 数据透视表的应用?
  • 构造矩阵:我得到了一个带有一系列偏移函数的解决方案,但想不出可行的方法来实现给定的空间问题
  • 通过求和将拆分的单元格转换为长数字:例如8 22 16 = 80 000 + 22 00 + 16. 使用带有文本的替代函数(长数字,“General”)我能够成功地为相邻的“元组”对引入分隔符(“|”)(例如我可能会得到“8|2216”、“822|16”,但是然后是一个“建立”公式,其中一个单元格取决于前一个单元格的转换值,因此再次需要一个,这让我回到了我设定的建议在上面
  • 仅供参考 - 矩阵考虑仅解决 2 元组,对于 n 维/组合,需要在其镜像副本上“传递”一串字符 - 例如{6,10,22} 将超过 {6,10,22},忽略重复值将产生如下梯形:
<头>
6 10 22
6 10 22
6 10 22

在副本“通过”原始(第一行)之后,我们有所需的组合(22,10,6)(在“对角线”这样的矩阵上)。这类似于傅立叶变换的工作方式(有点);但除此之外,构建这样的矩阵很诱人,但现阶段无法打扰。

结果可能是有人想出的更简单的方法(根据我考虑过的各种来源,我不会是唯一感到惊讶的人...)