如何在c#中将数值转换为Excel列名,而不使用直接从Excel中获取值的自动化。
Excel 2007的范围可能是1到16384,这是它支持的列数。结果值应以excel列名的形式出现,例如A、AA、AAA等。
如何在c#中将数值转换为Excel列名,而不使用直接从Excel中获取值的自动化。
Excel 2007的范围可能是1到16384,这是它支持的列数。结果值应以excel列名的形式出现,例如A、AA、AAA等。
当前回答
我的解决方案基于Graham, Herman Kan和desseim的回答,使用StringBuilder:
internal class Program
{
#region get_excel_col_name
/// <summary>
/// Returns the name of the column by its number
/// </summary>
/// <param name="col_num">Column number</param>
/// <returns>Column name</returns>
/// <remarks>Numbering columns from zero</remarks>
private static string get_excel_col_name(int col_num)
{
StringBuilder sb = new StringBuilder(2);
if (col_num >= 0)
{
do
{
sb.Insert(0, (char)(col_num % 26 + 65));
col_num /= 26;
}
while (--col_num >= 0);
}
return sb.ToString();
}
#endregion
private static void Main(string[] args)
{
Console.WriteLine(get_excel_col_name(34));//outputs AI
Console.ReadKey(true);
}
}
其他回答
抱歉,这是Python而不是c#,但至少结果是正确的:
def excel_column_number_to_name(column_number):
output = ""
index = column_number-1
while index >= 0:
character = chr((index%26)+ord('A'))
output = output + character
index = index/26 - 1
return output[::-1]
for i in xrange(1, 1024):
print "%4d : %s" % (i, excel_column_number_to_name(i))
通过这些测试用例:
列号:494286 => ABCDZ 列号:27 => 列号:52 => AZ
这是一个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;
};
似乎很多答案都比必要的要复杂得多。下面是一个基于上面描述的递归的通用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
int nCol = 127;
string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol >= 26)
{
int nChar = nCol % 26;
nCol = (nCol - nChar) / 26;
// You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now.
sCol = sChars[nChar] + sCol;
}
sCol = sChars[nCol] + sCol;
更新:Peter的评论是正确的。这就是我在浏览器中编写代码的结果。:-)我的解决方案是不编译,它是最左边的字母,它是在反向顺序构建字符串-现在都固定了。
除了bug之外,该算法基本上是将一个数字从10进制转换为26进制。
更新2:Joel Coehoorn是对的-上面的代码将返回AB为27。如果它是一个以26为底的实数,AA就等于A, Z之后的下一个数字就是BA。
int nCol = 127;
string sChars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol > 26)
{
int nChar = nCol % 26;
if (nChar == 0)
nChar = 26;
nCol = (nCol - nChar) / 26;
sCol = sChars[nChar] + sCol;
}
if (nCol != 0)
sCol = sChars[nCol] + sCol;
这是我在PHP中的超级后期实现。这个是递归的。我是在发现这篇文章之前写的。我想看看其他人是否已经解决了这个问题……
public function GetColumn($intNumber, $strCol = null) {
if ($intNumber > 0) {
$intRem = ($intNumber - 1) % 26;
$strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
}
return $strCol;
}