2

我正在处理一个 Excel 电子表格,我必须只使用一种类型的公式来处理大量数据。由于在公式中唯一必要的更改涉及字母,我想知道是否有一种方法可以制作一个程序,按照 Excel 列顺序(A、B、C...Z;AA、AB、AC... AZ;BA、BB、BC...BZ)。

就我而言,我需要每次将字母增加五个,所以这是我想要获得的代码类型:

#include <iostream>

using namespace std;

int main() {

 char x = 'B';
 char y = 'E';
 for (int z = 1; z < 2255; z++) {
   cout << "=SUMPRODUCT(SUBTOTAL(4,OFFSET(" << x << "1:" << y << "1,ROW(" << x << "1:" << x << "100)-ROW(" << x << "1),)))" << endl;
   x = x + 5;
   y= y + 5;
  }
  return 0;
}

当然它不会起作用,因为它超过了'z',但是,有没有办法做到这一点?

4

5 回答 5

1

一般解决方案说明

解决方案 1:自己创建 base-26 系统:

假设您有 26 个字母。所以首先让我们制作26个数字系统。我们为每个数字使用 1 个字节。我们创建了一个数字数组,然后当相加超过 26 时有时需要调整。

假设您当前的数字是 25。我们将其加 7,然后我们需要处理溢出,假设最大为 256(1 个字节),并且我们的数字限制为 26。因此调整将是 256-26=230。(我们在 short(16 位)上进行此计算,因此我们在 处溢出26+7=33 -> 33+230=263。因此,高字节将为 1,低字节将为 7。)

计算出溢出阈值(高于 1)后,我们可以将其添加到下一个数字,并在发生溢出时执行相同操作。

最后,为了显示,我们只需将 65 ('A') 添加到两个字节中的每一个。我们的最后一个字节将以 '\0' null 结尾,因此我们可以将其转换为字符串。

解决方案 2执行所有计算,然后将其转换为 26 基数:

在这种情况下,

number/26 = x

remainder r1 = (number%26)

我们将 r1 存储到一个字节中。

x/26 = x1

remainder r2 = (x%26)

我们将 r2 存储到下一个字节。

x1/26 = x2

remainder r3 = (x%26)

我们将 r3 存储到下一个字节。我们得到一个字符串r3 r2 r1 '\0',然后将 65 'A' 添加到每个字节。

于 2013-06-27T05:06:54.873 回答
0

The result you're trying to produce can be viewed as a base-27 number, using the characters 'A' through 'Z' as the 26 digits. It is a little unusual, in that 'A' is really '0', but when you get to a two-digit number, it's "AA", (where a normal two-digit would be BA -- i.e., just like the next number after 9 is 10). We have to do a fairly minor adjustment to compensate for that oddity.

You can do the counting with a normal int (or whatever) and then convert to base 27 when needed. Since I don't think it supports more columns than that, I've restricted this version to 2 digits, though extending to more would be fairly trivial:

std::string to_excel_column(int input) { 
    int digit1 = input % 26;
    int digit2 = input / 26;

    std::string result;
    if (input > 26)
        result.push_back(digit2 + 'A' - 1);
    result.push_back(digit1 + 'A');
    return result;
}
于 2013-06-27T05:34:03.697 回答
0

您可以在两个嵌套循环中执行此操作,都 from 'A'to 'Z',然后只需将两个字符附加在一起。将结果放入向量中。

要将单个字母添加'A''Z',请将它们添加到嵌套循环之前的向量中。

于 2013-06-27T04:53:12.670 回答
0

做这个:

x = (x + 5 > 'Z' ? x + 5 - 'Z' + 'A' : x + 5);
y = (y + 5 > 'Z' ? y + 5 - 'Z' + 'A' : y + 5);
于 2013-06-27T04:53:05.803 回答
0

作为一种选择,您可以创建一个由两个字符组成的新数据类型(类似于std::pair<char,char>并为此定义算术。

但是,我认为继续使用int(or unsigned int) 进行计数和算术会更简单,并定义一个to_col_heading将整数转换为 Excel 的一/二字符列标题的函数:

#include <string>
#include <iostream>
#include <stdexcept>
#include <iterator>

/* This is the function that performs
   the transformation. */    
std::string to_col_heading(unsigned i)
{
  if (i > 26+26*26)
    throw std::overflow_error
      ("Value too large for transformation into Excel column heading.");

  char char1 = 'A' + (i / 26) - 1;
  char char2 = 'A' + (i % 26);

  if (char1 < 'A')
    return std::string(&char2,&char2 + 1);
  else
    return std::string(&char1,&char1 + 1) + char2;
}

int main()
{
  std::ostream_iterator<std::string> out(std::cout,", ");
  for (unsigned i = 0 ; i < 26+26*26 ; i += 5)
    *out = to_col_heading(i);

  std::cout << std::endl;
  return 0;
}

输出:

A, F, K, P, U, Z, AE, AJ, AO, AT, AY, BD, BI, BN, BS, BX, CC, CH, CM, CR, CW, DB, DG, DL, DQ, DV, EA, EF, EK, EP, EU, EZ, FE, FJ, FO, FT, FY, GD, GI, GN, GS, GX, HC, HH, HM, HR, HW, IB, IG, IL, IQ, IV, JA, JF, JK, JP, JU, JZ, KE, KJ, KO, KT, KY, LD, LI, LN, LS, LX, MC, MH, MM, MR, MW, NB, NG, NL, NQ, NV, OA, OF, OK, OP, OU, OZ, PE, PJ, PO, PT, PY, QD, QI, QN, QS, QX, RC, RH, RM, RR, RW, SB, SG, SL, SQ, SV, TA, TF, TK, TP, TU, TZ, UE, UJ, UO, UT, UY, VD, VI, VN, VS, VX, WC, WH, WM, WR, WW, XB, XG, XL, XQ, XV, YA, YF, YK, YP, YU, YZ, ZE, ZJ, ZO, ZT, ZY,

为了支持最多 3 个(字母)数字的列标题,下面的函数起作用。它完全分别处理前 26 个值,以简化其余值的计算。我还介绍了一些静态常量,以更一致的方式处理 26 的幂。对于三位数,您需要 26 0、26 1和 26 2,但系统可以扩展为涵盖任意位数。

我确信有办法优化它以提高速度;这不是这里的重点。

std::string to_col_heading(unsigned i)
{
  const static unsigned pow1 = 26;
  const static unsigned pow2 = 26*26;
  const static unsigned max  = pow1 + pow2 + 26 * pow2;

  if (i < pow1)
    {
      char c = 'A' + i % pow1;
      return std::string(&c,&c+1);
    }

  if (i > max)
    throw std::overflow_error
      ("Value too large for transformation into Excel column heading.");

  i -= pow1;
  char char1 = 'A' + (i / pow2) - 1;
  char char2 = 'A' + (i%pow2) / pow1;
  char char3 = 'A' + i % pow1;

  if (char1 < 'A')
    return std::string(&char2,&char2 + 1) + char3;
  else
    return std::string(&char1,&char1 + 1) + char2 + char3;
}
于 2013-06-27T05:07:02.883 回答