没有 VBA 的迭代/循环替代

E33*_*E33 5 excel concatenation excel-formula 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)
Run Code Online (Sandbox Code Playgroud)

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

我受以下条件的约束:

  • Excel 2007,所以没有TEXTJOIN函数
  • 没有 VBA 或 UDF(由于安全策略)
  • 单个数字是动态的(即,我不能为 SUBSTITUTE 公式的“old_text”参数使用静态值)
  • 连接数据中单个数字的数量也是动态的(可能包含一个数字,也可能包含几十个不同的数字)

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

只是添加一些关于连接数据的信息:

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

JB-*_*007 1

高水平

\n
    \n
  1. 该解决方案的四个部分
  2. \n
  3. 它们满足先决条件(2007 兼容性、无 VB、无 Office 365 要求、无自定义 VB 函数、提供要连接的可变长度单元格的完整“动态”性质)
  4. \n
  5. 警告:据最佳知识/研究,不存在简约的单细胞功能,因此提出了一个临时步骤)
  6. \n
  7. 还有一个警告:我想将图形包裹在分隔数据周围的简单“黑客”是不可能的(请参阅\xe2\x98\xba 下面的“其他/各种”)
  8. \n
\n

第 1-4 部分

\n

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

\n

动态串联解决方案的 Excel 描述 - Excel 2007

\n

我还上传/修改了 Google 表格的要求(请参阅此处)\n第 1 部分和第 2 部分:

\n

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

\n

第1部分:

\n
=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")))\n
Run Code Online (Sandbox Code Playgroud)\n

注意:Google Sheets 无法识别 FilterXML,因此相应地修改了技术/功能。例如,可以使用第 2 部分中的分割单元格上的 counta 来确定(比上面提出的方法更容易/简单得多,尽管考虑到位于分割单元格右侧的任何单元格会干扰此方法的普通功能,但鲁棒性较差) 。

\n

第2部分:

\n

它可以是手动方法、一系列奇特的“中”和/或替代/左/右函数,也可以是以下 FilterXML 代码,根据各种来源(例如此处),该代码应与 Excel 2007 兼容:

\n
=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"))\n
Run Code Online (Sandbox Code Playgroud)\n

可以看出与第 1 部分(re:FilterXML)的共性 - 唯一的区别是计数(第 1 部分)已被替换为转换(乘法因子,如 OP's Q 中给出的)。

\n

第三部分

\n

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

\n
=IF(H12="","",IF(G24="","|","")&G24&H12&"|")\n
Run Code Online (Sandbox Code Playgroud)\n

第 4 部分

\n

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

\n
=OFFSET(H31,0,E31-1,1,1)\n
Run Code Online (Sandbox Code Playgroud)\n

其他/各种

\n

存在各种其他建议和“解决方法”;不幸的是,这些似乎在某种程度上达不到规定的先决条件,videlicit:

\n

a) 基于函数/公式\nb) 无 VB\nc) Excel 2007\nd) 动态(可变/未知数量的项)

\n
    \n
  1. 手动:例如 function = concatenate(transpose(desired range)),然后是 concatenate 函数的组成部分并按 F9 转换为计算值,这些值很容易应用于 concatenate 函数。缺点:相对于“自动化解决方案”而言非常耗时(需要为每个适用的玩具完成)。优点:不需要额外的“电子表格空间”,首先可以更快/更直接地实施。
  2. \n
  3. “构建”方法的变体:例如,根据第 3 部分,然而,仅此并不能确保对原始串联列表中未知数量的术语进行自动处理。
  4. \n
  5. 在之前的解决方案(此处)中已提到,但您可能在使用早期版本的 Excel 时有资格使用 Office 365 功能(请参阅此处的Office Insider )
  6. \n
  7. 其他提案(请注意,本论坛的上方/下方)提出了 textjoin (所以不确定这是否是理解问题或 \xe2\x98\xba 是什么)
  8. \n
  9. 是的,正如一开始所提到的,您可以使用简单的图表轻松实现所需的结果!只是为了好玩,以相反的顺序对数据进行排序,并将分割/分隔值作为条形图\'“x值”(根据定义,对于这种类型的图表,现在将沿着普通的笛卡尔\ ‘y/垂直\’轴)...
  10. \n
\n

图形化解决方案

\n

零分,但我认为这是一个有趣的发现!\n(如果仍然有疑问,如果我没有杀死除轴之外的所有内容,这就是“图表”的样子标签...):

\n

有趣的小图 - 可能是最快的解决方案!

\n

上述相关其他项目的大量参考文献,包括研究领域,如下:

\n\n

还有一件事...

\n

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

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

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

\n

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

\n