如何将列号(例如 127)转换为 Excel 列(例如 AA)
Posted
技术标签:
【中文标题】如何将列号(例如 127)转换为 Excel 列(例如 AA)【英文标题】:How to convert a column number (e.g. 127) into an Excel column (e.g. AA) 【发布时间】:2008-10-08 06:55:01 【问题描述】:如何在 C# 中将数字转换为 Excel 列名,而不使用直接从 Excel 中自动获取值。
Excel 2007 的可能范围为 1 到 16384,这是它支持的列数。结果值应采用 excel 列名的形式,例如A、AA、AAA等。
【问题讨论】:
不要忘记可用列的数量是有限制的。例如。 * Excel 2003 (v11) 达到 IV、2^8 或 256 列)。 * Excel 2007 (v12) 增加到 XFD、2^14 或 16384 列。 How do I find the Excel column name that corresponds to a given integer?的可能重复 这个问题被标记为 C# 和 excel。我将此问题标记为已过时,因为我们生活在 2016 年并且有 EPPLUS。一个常用的 C# 库,用于在服务器上创建高级 Excel 电子表格。可通过以下方式获得:GNU 库通用公共许可证 (LGPL)。使用 EPPlus 可以轻松获取 Column 字符串。 请注意,与 Excel 版本相比,行和列限制更多地取决于文件格式,并且每个工作簿可能不同。如果将同一工作簿保存为较旧或较新的格式,它们甚至可以更改。 @Tony_KiloPapaMikeGolf 我不认为这已经过时了。事实上,EPPLUS 已经改变了他们的许可,由于各种原因,这可能并不适合所有人。另外,如果你只需要这么简单的东西,为什么还要带一个图书馆呢?我正在使用 OpenXML 以 Excel 格式导出数据,我只需要几个算法,就像这里所要求的那样。为什么要添加一个库?需求不同。这个问题并没有过时,并且与简单的用例相关。也就是说,EPPLUS 是一个非常酷的库。 ;) 【参考方案1】:我正在尝试在 Java 中做同样的事情... 我写了以下代码:
private String getExcelColumnName(int columnNumber)
int dividend = columnNumber;
String columnName = "";
int modulo;
while (dividend > 0)
modulo = (dividend - 1) % 26;
char val = Character.valueOf((char)(65 + modulo));
columnName += val;
dividend = (int)((dividend - modulo) / 26);
return columnName;
现在,一旦我使用 columnNumber = 29 运行它,它就会给我结果 =“CA”(而不是“AC”) 有什么我想念的吗? 我知道我可以通过 StringBuilder 扭转它....但是看着格雷厄姆的回答,我有点困惑....
【讨论】:
格雷厄姆说:columnName = Convert.ToChar(65 + modulo).ToString() + columnName
(即值 + ColName)。哈桑说:columnName += val;
(即 ColName + 值)
您是在附加新字符而不是在其前面。应该是columnName = columnName + val
。【参考方案2】:
简洁优雅的Ruby版本:
def col_name(col_idx)
name = ""
while col_idx>0
mod = (col_idx-1)%26
name = (65+mod).chr + name
col_idx = ((col_idx-mod)/26).to_i
end
name
end
【讨论】:
【参考方案3】:NodeJS 实现:
/**
* getColumnFromIndex
* Helper that returns a column value (A-XFD) for an index value (integer).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://***.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa/3444285#3444285
* @param numVal: Integer
* @return String
*/
getColumnFromIndex: function(numVal)
var dividend = parseInt(numVal);
var columnName = '';
var modulo;
while (dividend > 0)
modulo = (dividend - 1) % 26;
columnName = String.fromCharCode(65 + modulo) + columnName;
dividend = parseInt((dividend - modulo) / 26);
return columnName;
,
感谢Convert excel column alphabet (e.g. AA) to number (e.g., 25)。反过来:
/**
* getIndexFromColumn
* Helper that returns an index value (integer) for a column value (A-XFD).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://***.com/questions/9905533/convert-excel-column-alphabet-e-g-aa-to-number-e-g-25
* @param strVal: String
* @return Integer
*/
getIndexFromColumn: function(val)
var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', i, j, result = 0;
for (i = 0, j = val.length - 1; i < val.length; i += 1, j -= 1)
result += Math.pow(base.length, j) * (base.indexOf(val[i]) + 1);
return result;
【讨论】:
【参考方案4】:每种方式的F#版本
let rec getExcelColumnName x = if x<26 then int 'A'+x|>char|>string else (x/26-1|>c)+ c(x%26)
请原谅最小化,正在开发更好的https://***.com/a/4500043/57883版本
和相反的方向:
// return values start at 0
let getIndexFromExcelColumnName (x:string) =
let a = int 'A'
let fPow len i =
Math.Pow(26., len - 1 - i |> float)
|> int
let getValue len i c =
int c - a + 1 * fPow len i
let f i = getValue x.Length i x.[i]
[0 .. x.Length - 1]
|> Seq.map f
|> Seq.sum
|> fun x -> x - 1
【讨论】:
【参考方案5】:在这里感谢您的回答!帮助我想出了这些帮助函数,以便与我在 Elixir/Phoenix 中使用的 Google Sheets API 进行一些交互
这是我想出的(可能会使用一些额外的验证和错误处理)
在灵药中:
def number_to_column(number) do
cond do
(number > 0 && number <= 26) ->
to_string([(number + 64)])
(number > 26) ->
div_col = number_to_column(div(number - 1, 26))
remainder = rem(number, 26)
rem_col = cond do
(remainder == 0) ->
number_to_column(26)
true ->
number_to_column(remainder)
end
div_col <> rem_col
true ->
""
end
end
还有反函数:
def column_to_number(column) do
column
|> to_charlist
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn(char, idx, acc) ->
((char - 64) * :math.pow(26,idx)) + acc
end)
|> round
end
还有一些测试:
describe "test excel functions" do
@excelTestData ["A", 1, "Z",26, "AA", 27, "AB", 28, "AZ", 52,"BA", 53, "AAA", 703]
test "column to number" do
Enum.each(@excelTestData, fn(input, expected_result) ->
actual_result = BulkOnboardingController.column_to_number(input)
assert actual_result == expected_result
end)
end
test "number to column" do
Enum.each(@excelTestData, fn(expected_result, input) ->
actual_result = BulkOnboardingController.number_to_column(input)
assert actual_result == expected_result
end)
end
end
【讨论】:
【参考方案6】:这是根据 Graham 的代码编写的 javascript 版本
function (columnNumber)
var dividend = columnNumber;
var columnName = "";
var modulo;
while (dividend > 0)
modulo = (dividend - 1) % 26;
columnName = String.fromCharCode(65 + modulo) + columnName;
dividend = parseInt((dividend - modulo) / 26);
return columnName;
;
【讨论】:
【参考方案7】:之前的大部分答案都是正确的。这是将列号转换为 excel 列的另一种方法。 如果我们将此视为基本转换,则解决方案相当简单。只需将列号转换为基数 26,因为只有 26 个字母。 以下是您可以执行此操作的方法:
步骤:
将列设置为商
从商变量中减去一个(来自上一步),因为我们需要以 ascii table 结束,其中 97 是 a。
除以 26 得到余数。
将 +97 添加到余数并转换为 char(因为 97 在 ASCII 表中是“a”) 商成为新的商/26(因为我们可能会超过 26 列) 继续这样做,直到商大于0,然后返回结果这是执行此操作的代码:)
def convert_num_to_column(column_num):
result = ""
quotient = column_num
remainder = 0
while (quotient >0):
quotient = quotient -1
remainder = quotient%26
result = chr(int(remainder)+97)+result
quotient = int(quotient/26)
return result
print("--",convert_num_to_column(1).upper())
【讨论】:
【参考方案8】:此 sn-p 适用于 A 到 ZZ 列名称
string columnName = columnNumber > 26 ? Convert.ToChar(64 + (columnNumber / 26)).ToString() + Convert.ToChar(64 + (columnNumber % 26)) : Convert.ToChar(64 + columnNumber).ToString();
【讨论】:
【参考方案9】:我在 VB.NET 2003 中使用这个,它运行良好...
Private Function GetExcelColumnName(ByVal aiColNumber As Integer) As String
Dim BaseValue As Integer = Convert.ToInt32(("A").Chars(0)) - 1
Dim lsReturn As String = String.Empty
If (aiColNumber > 26) Then
lsReturn = GetExcelColumnName(Convert.ToInt32((Format(aiColNumber / 26, "0.0").Split("."))(0)))
End If
GetExcelColumnName = lsReturn + Convert.ToChar(BaseValue + (aiColNumber Mod 26))
End Function
【讨论】:
【参考方案10】:另一种解决方案:
private void Foo()
l_ExcelApp = new Excel.ApplicationClass();
l_ExcelApp.ReferenceStyle = Excel.XlReferenceStyle.xlR1C1;
// ... now reference by R[row]C[column], Ex. A1 <==> R1C1, C6 <==> R3C6, ...
在此处查看更多信息 - Cell referencing in Excel for everyone! by Dr Nitin Paranjape
【讨论】:
ApplicationClass 类型自 Excel 2003 以来一直不可行。停止使用错误的编码。【参考方案11】:public static string ConvertToAlphaColumnReferenceFromInteger(int columnReference)
int baseValue = ((int)('A')) - 1 ;
string lsReturn = String.Empty;
if (columnReference > 26)
lsReturn = ConvertToAlphaColumnReferenceFromInteger(Convert.ToInt32(Convert.ToDouble(columnReference / 26).ToString().Split('.')[0]));
return lsReturn + Convert.ToChar(baseValue + (columnReference % 26));
【讨论】:
你能补充一些解释吗?【参考方案12】:在 VB.Net 2005 中使用它:
Private Function ColumnName(ByVal ColumnIndex As Integer) As String
Dim Name As String = ""
Name = (New Microsoft.Office.Interop.Owc11.Spreadsheet).Columns.Item(ColumnIndex).Address(False, False, Microsoft.Office.Interop.Owc11.XlReferenceStyle.xlA1)
Name = Split(Name, ":")(0)
Return Name
End Function
【讨论】:
好主意。但糟糕的表现明智。隐式地新建一个对象,然后使用另外四个点来调用最终的 Address 方法将导致一些可怕的互操作编组。肯定需要重写。【参考方案13】:如果您想以编程方式引用单元格,那么如果您使用工作表的 Cells 方法,您将获得更具可读性的代码。它采用行和列索引而不是传统的单元格引用。与 Offset 方法非常相似。
【讨论】:
?单元格可能是在 Excel 中引用范围的最糟糕的方式。它的表现令人震惊。偏移或只是 Worksheet.Range 会好得多。【参考方案14】:这是我在 Python 中的做法。算法解释如下:
alph = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z')
def labelrec(n, res):
if n<26:
return alph[n]+res
else:
rem = n%26
res = alph[rem]+res
n = n/26-1
return labelrec(n, res)
函数 labelrec 可以用数字和空字符串调用,例如:
print labelrec(16383, '')
这就是它起作用的原因: 如果十进制数的写入方式与 Excel 工作表的列相同,则数字 0-9 将正常写入,但 10 将变为“00”,然后 20 将变为“10”,依此类推。映射几个数字:
0 - 0
9 - 9
10 - 00
20 - 10
100 - 90
110 - 000
1110 - 0000
所以,模式很清楚。从单位开始,如果一个数字小于 10,它的表示与数字本身相同,否则您需要通过将剩余的数字减去 1 并递归来调整剩余的数字。当数量小于 10 时可以停止。
同样的逻辑适用于上述解决方案中以 26 为底的数字。
附:如果您希望数字从 1 开始,请在将输入数字减 1 后调用相同的函数。
【讨论】:
【参考方案15】:(我意识到这个问题与 C# 有关,但是如果有人阅读需要使用 Java 做同样的事情,那么以下内容可能会有用)
事实证明,这可以使用Jakarta POI 中的“CellReference”类轻松完成。此外,转换可以通过两种方式完成。
// Convert row and column numbers (0-based) to an Excel cell reference
CellReference numbers = new CellReference(3, 28);
System.out.println(numbers.formatAsString());
// Convert an Excel cell reference back into digits
CellReference reference = new CellReference("AC4");
System.out.println(reference.getRow() + ", " + reference.getCol());
【讨论】:
【参考方案16】:我今天刚要做这个工作,我的实现使用递归:
private static string GetColumnLetter(string colNumber)
if (string.IsNullOrEmpty(colNumber))
throw new ArgumentNullException(colNumber);
string colName = String.Empty;
try
var colNum = Convert.ToInt32(colNumber);
var mod = colNum % 26;
var div = Math.Floor((double)(colNum)/26);
colName = ((div > 0) ? GetColumnLetter((div - 1).ToString()) : String.Empty) + Convert.ToChar(mod + 65);
finally
colName = colName == String.Empty ? "A" : colName;
return colName;
这将数字作为字符串的方法和以“0”开头的数字(A = 0)
【讨论】:
【参考方案17】:Objective-C 实现:
-(NSString*)getColumnName:(int)n
NSString *name = @"";
while (n>0)
n--;
char c = (char)('A' + n%26);
name = [NSString stringWithFormat:@"%c%@",c,name];
n = n/26;
return name;
SWIFT 实施:
func getColumnName(n:Int)->String
var columnName = ""
var index = n
while index>0
index--
let char = Character(UnicodeScalar(65 + index%26))
columnName = "\(char)\(columnName)"
index = index / 26
return columnName
答案基于:https://***.com/a/4532562/2231118
【讨论】:
【参考方案18】:打字稿
function lengthToExcelColumn(len: number): string
let dividend: number = len;
let columnName: string = '';
let modulo: number = 0;
while (dividend > 0)
modulo = (dividend - 1) % 26;
columnName = String.fromCharCode(65 + modulo).toString() + columnName;
dividend = Math.floor((dividend - modulo) / 26);
return columnName;
【讨论】:
【参考方案19】:似乎很多答案比必要的复杂得多。这是基于上述递归的通用 Ruby 答案:
这个答案的一个好处是它不限于英文字母的 26 个字符。您可以在COLUMNS
常量中定义您喜欢的任何范围,它会做正确的事情。
# vim: ft=ruby
class Numeric
COLUMNS = ('A'..'Z').to_a
def to_excel_column(n = self)
n < 1 ? '' : begin
base = COLUMNS.size
to_excel_column((n - 1) / base) + COLUMNS[(n - 1) % base]
end
end
end
# verify:
(1..52).each |i| printf "%4d => %4s\n", i, i.to_excel_column
这会打印以下内容,例如:
1 => A
2 => B
3 => C
....
33 => AG
34 => AH
35 => AI
36 => AJ
37 => AK
38 => AL
39 => AM
40 => AN
41 => AO
42 => AP
43 => AQ
44 => AR
45 => AS
46 => AT
47 => AU
48 => AV
49 => AW
50 => AX
51 => AY
52 => AZ
【讨论】:
【参考方案20】:这是编码测试中常见的问题。 它有一些限制: 每行最大列数= 702 输出应该有行号+列名,例如703 的答案是 2A。 (注意:我刚刚从另一个答案修改了现有代码) 这是相同的代码:
static string GetExcelColumnName(long columnNumber)
//max number of column per row
const long maxColPerRow = 702;
//find row number
long rowNum = (columnNumber / maxColPerRow);
//find tierable columns in the row.
long dividend = columnNumber - (maxColPerRow * rowNum);
string columnName = String.Empty;
long modulo;
while (dividend > 0)
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
return rowNum+1+ columnName;
【讨论】:
【参考方案21】:T-SQL (SQL SERVER 18)
第一页解决方案的副本
CREATE FUNCTION dbo.getExcelColumnNameByOrdinal(@RowNum int)
RETURNS varchar(5)
AS
BEGIN
DECLARE @dividend int = @RowNum;
DECLARE @columnName varchar(max) = '';
DECLARE @modulo int;
WHILE (@dividend > 0)
BEGIN
SELECT @modulo = ((@dividend - 1) % 26);
SELECT @columnName = CHAR((65 + @modulo)) + @columnName;
SELECT @dividend = CAST(((@dividend - @modulo) / 26) as int);
END
RETURN
@columnName;
END;
【讨论】:
【参考方案22】:这是一个基于零的列索引的更简单解决方案
public static string GetColumnIndexNumberToExcelColumn(int columnIndex)
int offset = columnIndex % 26;
int multiple = columnIndex / 26;
int initialSeed = 65;//Represents column "A"
if (multiple == 0)
return Convert.ToChar(initialSeed + offset).ToString();
return $"Convert.ToChar(initialSeed + multiple - 1)Convert.ToChar(initialSeed + offset)";
【讨论】:
【参考方案23】:看到另一个 VBA 答案 - 这可以在 excel-vba 中使用 1 行 UDF 完成:
Function GetColLetter(ByVal colID As Integer) As String
If colID > Columns.Count Then
Err.Raise 9, , "Column index out of bounds"
Else
GetColLetter = Split(Cells(1, colID).Address, "$")(1)
End If
End Function
【讨论】:
超级。这是@paulma 的变体【参考方案24】:Microsoft Excel Miniature,速成公式。
嗨,
这是从数字中获取 Excel 字符列标题的一种方法......
我为 Excel 单元格创建了一个公式。
(即我采取了不使用VBA编程的方法。)
该公式查看一个包含数字的单元格,并告诉您该列是什么——用字母表示。
在附图中:
我将 1、2、3 等放在顶行一直到 ABS 列。 我将公式一直粘贴到第二行,一直到 ABS。 我的公式查看第 1 行并将数字转换为 Excel 的列标题 ID。 我的公式适用于 702 (zz) 以内的所有数字。我这样做是为了证明公式有效,因此您可以查看公式的输出并查看上面的列标题,并轻松直观地验证公式是否有效。 :-)
=CONCATENATE(MID("_abcdefghijklmnopqrstuvwxyz",(IF(MOD(K1,26)>0,INT(K1/26)+1,(INT(K1/26)))),1),MID(" abcdefghijklmnopqrstuvwxyz",IF(MOD(K1,26)=0,26,MOD(K1,26)),1))
下划线用于调试目的 - 让您知道有一个实际空间并且它工作正常。
使用上面的这个公式——无论你在 K1 中输入什么——这个公式都会告诉你列标题是什么。
当前形式的公式仅包含 2 位数字 (ZZ),但可以修改为添加第三个字母 (ZZZ)。
【讨论】:
【参考方案25】:这是我在 python 中的解决方案
import math
num = 3500
row_number = str(math.ceil(num / 702))
letters = ''
num = num - 702 * math.floor(num / 702)
while num:
mod = (num - 1) % 26
letters += chr(mod + 65)
num = (num - 1) // 26
result = row_number + ("".join(reversed(letters)))
print(result)
【讨论】:
【参考方案26】: public string ToBase26(int number)
if (number < 0) return String.Empty;
int remainder = number % 26;
int value = number / 26;
return value == 0 ?
String.Format("0", Convert.ToChar(65 + remainder)) :
String.Format("01", ToBase26(value - 1), Convert.ToChar(65 + remainder));
【讨论】:
这不仅仅是一个简单的 base-26 转换。阅读其他答案。 假设第一列是 0。0 将返回 A,26 将返回 AA,702 将返回 AAA。我的和第一个正确答案的不同之处在于,它以 1 开头,而我的以 0 开头。这就是我的理解。如果我错了,请纠正我。 @dirn 你错了。以 10 为底数到 26,将 11 转换为 A,而不是 1 到 A。以上是关于如何将列号(例如 127)转换为 Excel 列(例如 AA)的主要内容,如果未能解决你的问题,请参考以下文章