我需要知道一个电子表格的列名,其中给定的起始列数最多为n列 假设起始栏是“AB”,我想知道99列之后的列(标签)。
对于那些需要Ralph回答T-SQL风格的人来说
Create FUNCTION fsExcelValueToColum(@value int) returns varchar(3) as
begin
DECLARE @DIGIT INT,@RV VARCHAR(3);set @rv=''
IF @VALUE=0 RETURN @rv
WHILE @VALUE > 0
BEGIN
SET @DIGIT = @VALUE % 26
IF @DIGIT = 0
BEGIN
set @RV=@RV+'Z'
set @RV=@RV+dbo.fsExcelValueToColum(@value /26 -1)
return @rv
END
set @rv=@rv+char(@digit+64)
set @value=(@value-@digit) /26
END
return @rv
end
USE [ecs]
GO
/****** Object: UserDefinedFunction [dbo].[fnExcelColumnToValue] Script Date: 12/06/2009 10:33:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[fnExcelColumnToValue](@Column varchar(3)) returns int as
Begin
--declare @column varchar(10); select @column = 'AC'
declare @value int, @pow int,@i int,@n int
select @pow=1,@VALUE=0,@I=LEN(@COLUMN)
SET @I=LEN(@COLUMN)
WHILE @I >= 1
BEGIN
SET @VALUE=@VALUE+@POW*((ASCII(SUBSTRING(UPPER(@COLUMN),@I,1)) - 65) +1)
SET @POW=@POW *26
SET @I=@I-1
END
return @value
end
答案 0 :(得分:5)
将字符A
,B
,...,Z
视为代表值1,2,... 26(您不能将其视为因为没有代表0的字符,也没有我们不想要的字符,例如,AA
表示0)。因此,我们必须采取一些技巧来解决这个问题:
static int ColumnToValue(string column) {
int value = 0;
int pow = 1;
for (int i = column.Length - 1; i >= 0; i--) {
value += pow * (column[i] - 'A' + 1);
pow *= 26;
}
return value;
}
static string ValueToColumn(int value) {
if (value == 0) {
return string.Empty;
}
StringBuilder sb = new StringBuilder();
while (value > 0) {
int digit = value % 26;
if (digit == 0) {
sb.Insert(0, 'Z');
return sb.Insert(0, ValueToColumn(value / 26 - 1)).ToString();
}
sb.Insert(0,(char)(digit + 'A' - 1));
value = (value - digit) / 26;
}
return sb.ToString();
}
那样
Console.WriteLine(ValueToColumn(ColumnToValue("AB") + 99));
输出DW
和
Console.WriteLine(ValueToColumn(ColumnToValue("AB") - 2));
输出Z
。很显然,你可以将它全部包装在一个很好的课程中,使它流利或者你有什么。
说明:例如,考虑值702和通常的base-26表示法,其中有一个数字代表0(我将使用符号_
来表示这个神奇的数字,这样我们就不会在值0和数字0
之间混淆。让我们尝试将702(十进制)转换为base-26。通常的算法是计算702%26,它是0,因此我们将最后一位数字设为_
。然后我们将除以26得到27.我们会注意到27%26是1,所以倒数第二位是A
。然后我们将除以26得到1,计算1%26得到1并报告最高有效数字为A
。我们将返回AA_
作为在base-26中表示702的字符串,其中包含数字(_
= 0,A
= 1,... Z
= 26)(检查: 1 * 26 ^ 2 + 1 * 26 ^ 1 + 0 * 26 = 702)。出于我们的目的,这是错误的。我们想要找回字符串ZZ
(因为我们有26位A
,B
,C
,... Z
代表1,2 ,. .. 26(记住,没有数字表示值0!),以便ZZ
= 26 * 26 ^ 1 + 26 * 26 ^ 0 = 702)。事实证明,在我们的系统中,与模数一致的数字26应该具有最低有效数字Z
。所以这表明我们的算法应该检查并查看value
是否与0模26一致。如果是,则前置Z
,然后在前面加上代表值value / 26 - 1
的字符串。这是您在上面看到的算法。
答案 1 :(得分:1)
我刚才在Clipper(旧的XBASE编译器)
中写了这个 if nColumn <= 26 // Column 26 or less ?
retval := chr(nColumn+64)
else
temp := int(nColumn/26) // Compute first letter
remd := nColumn % 26 // and second letter and
retval:= if(remd=0,chr(temp+63)+"Z",;
chr(temp+64)+chr(remd+64))
endif
这适用于最多256列的电子表格,我不确定除此之外的列的公式是否相同。我不确定您使用的是哪种编程语言,但Clipper代码非常简单......
答案 2 :(得分:1)
这是我的价值(快速写入 - 我确信它可以整理): -
public static string ToAlpha(int index)
{
if (index <= 0)
{
throw new ArgumentOutOfRangeException("index");
}
--index;
var chars = new List<char>();
int x = index;
do
{
int r = x % 26;
chars.Insert(0, Convert.ToChar(65 + r));
x /= 26;
} while (x > 26);
if (x > 0)
{
chars.Insert(0, Convert.ToChar(64 + x));
}
return new string(chars.ToArray());
}
public static int ToNumeric(string index)
{
int total = 0;
var chars = index.ToCharArray();
int chrIndex = chars.Length - 1;
foreach (char chr in chars)
{
total += (Convert.ToInt32(chr) - 64) * (int)(Math.Pow(26d, (double)chrIndex));
--chrIndex;
}
return total;
}
用法
string input = "AB";
string output = ToAlpha(ToNumeric(input) + 99);