【问题标题】:Converting Excel column letters to corresponding column numbers将 Excel 列字母转换为相应的列号
【发布时间】:2013-03-06 23:15:42
【问题描述】:

我正在创建一个类来帮助创建 excel 文件(第二个问题)。我有一个成员函数,它在特定的行和列位置创建一个单元格并将其保存到一个数组中。

ExcelSheet::SetValue(int row, int column, std::string szValue) {
    myWorksheet[row][column] = szValue;
}

但我重载了该函数,可以选择将列指定为字母/数字组合,就像在 Excel 中一样。我希望能够将诸如“A3”之类的输入转换为第 3 行第 1 列,或将 AB19 转换为第 19 行第 28 列。即,

ExcelSheet::SetValue(std::string szCell, std::string value) {
    // search for the alphabetical part of szCell using regex and
    // convert it to a column number
    myWorksheet[row][column] = szValue;
}

Excel 列模式如下:

A, B, C, D, E... Z (1-26)  
AA, AB, AC, AD, AE... AZ (27-52)  
BA, BB, BC, BD, BE... BZ (53-78)  
...  
ZA, ZB, ZC... ZZ  
AAA, AAB, AAC... AAZ  
ABA, ABB, ABC... ABZ  
...  
AZA, AZB, AZC... AZZ  
BAA, BAB, BAC... BAZ  
...  

所以我认为某种基于 26 的循环可以解决问题,但我什至不知道在实现它时从哪里开始。

更新:

我几乎可以工作的代码:它可以编译,但由于某些不清楚的原因没有正确获取行。

#include <vector>
#include <string>
#include <iostream>
#include <regex>


class VectorClass {
    std::vector<std::string> vectorString;
public:
    void PrintVector(std::string szValue) {
        std::string str = "space";
        vectorString.push_back(szValue);
        vectorString.push_back(str);
        std::cout << "Loop:" << std::endl;
        for(int i=0; i < vectorString.size(); i++) {
            std::cout << vectorString[i] << std::endl;
        }
    }
    int GetColumn(std::string szValue) {
        std::regex rgx("^([a-zA-Z]+)");
        std::smatch result;
        if( regex_search(szValue, result, rgx) ) {
            std::string szResult = result[0];
            int numletters = szResult.length();
            const char * colstr = szResult.c_str();
            //char colstr[5];
            //int numofletters = 0;
            //for(int n=0;n<szResult.length();n++) {
            //  colstr[n] = szResult.substr(n,1);
            //  numofletters++;
            //}
            //char colstr[]="AEF";
            int col=0;
            for(int i=0; i<numletters; i++) {
                col = 26*col + colstr[i] - 'A' + 1;
            }
            return col;
            //return atoi(szResult.c_str());
        }
        else
            return -1;
    }
    int GetRow(std::string szValue)  {
        std::regex rgx("^[a-zA-Z]+(\d+)$");
        std::smatch result;
        if( regex_search(szValue, result, rgx) ) {
            std::cout << "test: " << result.size() << std::endl;
            for(size_t i=0; i<result.size(); ++i) {
                std::cout << result[i] << std::endl;
            }
            std::string szResult = result[0];
            return atoi(szResult.c_str());
        }
        else
            return -1;
    }
};

int main () {
    VectorClass myclass;
    //myclass.PrintVector("ship");
    std::cout << "A1 = Column " << myclass.GetColumn("A1") << ", Row " << myclass.GetRow("A1") << std::endl;
    std::cout << "B32 = Column " << myclass.GetColumn("B32") << ", Row " << myclass.GetRow("B32") << std::endl;
    std::cout << "Z65 = Column " << myclass.GetColumn("Z65") << ", Row " << myclass.GetRow("Z65") << std::endl;
    std::cout << "AA12 = Column " << myclass.GetColumn("AA12") << ", Row " << myclass.GetRow("AA12") << std::endl;
    std::cout << "AB366 = Column " << myclass.GetColumn("AB366") << ", Row " << myclass.GetRow("AB366") << std::endl;
    std::cout << "FAB43 = Column " << myclass.GetColumn("ZAB43") << ", Row " << myclass.GetRow("ZAB43") << std::endl;
    std::cout << "ZZZ43456 = Column " << myclass.GetColumn("XDE43456") << ", Row " << myclass.GetRow("XDE43456") << std::endl;
    std::cin.get();
    return 0;
}

【问题讨论】:

    标签: c++ excel visual-c++


    【解决方案1】:

    请注意,一个字符有一个 ASCII 值,您可以从以下获取列:

    char colstr[]="AEF";
    int ii, col=0;
    for(ii=0; ii<3; ii++) {
        col = 26*col + colstr[ii] - 'A' + 1;
    }
    

    需要注意的几点: - 我使用 char[] - 一个字符数组 - 来存储字符串。这使得访问 ASCII 值变得微不足道。 - 我将循环硬连接到 3 - 如果您的列标签长度不同,您可能想要解决这个问题 - 单引号中的值“A”是字符“A”,因此 ASCII 值是 65。

    编辑:由于您似乎无法获取行值,因此这里有一个非常简单的 (C) 函数,可以让您两者兼得 - 以及一些显示一些示例的代码。我无法编译您的代码 - 显然我的机器上没有库......我假设传递给函数的标签格式正确:只有字母后跟只有数字。它确实使用 toupper() 函数处理小写字母(注意 - 这是您的代码没有做的事情......)。我弄清楚最后一个字母在哪里,然后对这两个部分进行操作。我在row 和col 参数指向的位置返回行和列的值。

    #include <stdio.h>
    #include <stdlib.h>
    
    void rc(char * cellAddr, int *row, int *col) {
      int ii=0, jj, colVal=0;
      while(cellAddr[ii++] >= 'A') {};
      ii--;
      // ii now points to first character of row address
      for(jj=0;jj<ii;jj++) colVal = 26*colVal + toupper(cellAddr[jj]) -'A' + 1;
      *col = colVal;
      *row = atoi(cellAddr+ii);
    }
    
    int main() {
        int row, col;
        char cellAddr1[] = "A123";
        char cellAddr2[] = "aB321";
        char cellAddr3[] = "ABCA6543";
        rc(cellAddr1, &row, &col);
        printf("for %s the row is %d and the column is %d\n", cellAddr1, row, col);
        rc(cellAddr2, &row, &col);
        printf("for %s the row is %d and the column is %d\n", cellAddr2, row, col);
        rc(cellAddr3, &row, &col);
        printf("for %s the row is %d and the column is %d\n", cellAddr3, row, col);
    }
    

    这给我的输出是:

    for A123 the row is 123 and the column is 1
    for aB321 the row is 321 and the column is 28
    for ABCA6543 the row is 6543 and the column is 19007
    

    【讨论】:

    • 基本上逆向遍历字符串,将每个字母的 [ASCII value-64] * [26 ^ [position-1]] 相加(其中位置是左右位置)
    • 怎么得到 ASCII 值?
    • 在 C++ 中?不知道,但我肯定用谷歌搜索几分钟就会回答这个问题。
    • 当你分配给char时,它是一个单字节,其数值是ASCII码。
    • 谢谢。我能够让你的代码工作,但由于某种原因,我很难做我认为很简单的事情:获得行。将我的代码添加到我的问题中。
    【解决方案2】:

    在 Java 中,以防万一有人想要 java 版本

    import java.util.*;
    import java.lang.*;
    import java.io.*;
    
    class Ideone
    {
    public static void main (String[] args) throws java.lang.Exception
    {
        rowColFromA1("C5");
        rowColFromA1("$AB123456789");
        rowColFromA1("$C$5");
        rowColFromA1("C$5");
        rowColFromA1("$C5");
        rowColFromA1("$D5");
        rowColFromA1("$aC$5");
        rowColFromA1("$c$5");
        rowColFromA1("cBa$99");
        rowColFromA1("cBa$");
        rowColFromA1("99");
        rowColFromA1("$K$34");
    }
    
    public static int[] rowColFromA1(String a1ref) {
          int ii=0, jj, colVal=0;
          char[] cellAddr = a1ref.toCharArray();
          int[] rowCol = new int[2];
          int endOfCol;
    
          try {       
            while(cellAddr[ii] >= 'A' || cellAddr[ii] == '$' ) { ii++;};
            endOfCol = (cellAddr[ii-1] == '$') ? ii-1 : ii;
          } catch (ArrayIndexOutOfBoundsException aiobe) 
          { rowCol[0] = 1; rowCol[1] = 1; return rowCol;} 
          // skip $ of col, if any
          jj = (cellAddr[0] == '$') ? 1 : 0;
    
    
          // ii now points to first character of row address
          for(;jj<endOfCol;jj++) colVal = 26*colVal + Character.toUpperCase(cellAddr[jj]) -'A' + 1;
          rowCol[1] = (colVal > 0) ? colVal : 1;
    
          int rowVal = 0;
          for (;ii < cellAddr.length; ii++)
            rowVal = rowVal * 10 + cellAddr[ii] - '0';
    
          rowCol[0] = (rowVal > 0) ? rowVal : 1;
          System.out.println("R"+ rowCol[0]+"C"+rowCol[1]);
    
          return rowCol;
        }
    
    }
    

    在线java ide:http://ideone.com/69ISK8

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-13
      • 2012-09-29
      • 2010-11-19
      • 1970-01-01
      • 2014-02-09
      • 1970-01-01
      相关资源
      最近更新 更多