特定の整数に対応する Excel の列名を見つけるにはどうすればよいですか?[重複]
-
09-06-2019 - |
質問
この質問にはすでに答えがあります:
列名はどのように決定しますか (例:Excelのn列目の「AQ」または「BH」)?
編集:これを決定するための言語に依存しないアルゴリズムが、ここでの主な目標です。
解決
私はかつて、まさにそのタスクを実行するために次の関数を作成しました。
public static string Column(int column)
{
column--;
if (column >= 0 && column < 26)
return ((char)('A' + column)).ToString();
else if (column > 25)
return Column(column / 26) + Column(column % 26 + 1);
else
throw new Exception("Invalid Column #" + (column + 1).ToString());
}
他のヒント
ここが一番きれいです 正しい 私が思いつく解決策は次のとおりです (Java ですが、好きな言語を自由に使用してください)。
String getNthColumnName(int n) {
String name = "";
while (n > 0) {
n--;
name = (char)('A' + n%26) + name;
n /= 26;
}
return name;
}
ただし、このコードに間違いを見つけた場合は、ぜひお知らせください。ありがとうございます。
言語に依存しないアルゴリズムは次のようになります。
function getNthColumnName(int n) {
let curPower = 1
while curPower < n {
set curPower = curPower * 26
}
let result = ""
while n > 0 {
let temp = n / curPower
let result = result + char(temp)
set n = n - (curPower * temp)
set curPower = curPower / 26
}
return result
このアルゴリズムでは、16,000 列を超える列を処理できるように Excel が再度アップグレードされた場合も考慮されます。本当にやりすぎた場合は、追加の値を渡して 26 のインスタンスを別の数値に置き換えて、代替アルファベットに対応することもできます。
ありがとう、ジョセフ・スターテバント!あなたのコードは完璧に機能します。vbscript で必要だったので、私のバージョンを共有したいと思いました。
Function ColumnLetter(ByVal intColumnNumber)
Dim sResult
intColumnNumber = intColumnNumber - 1
If (intColumnNumber >= 0 And intColumnNumber < 26) Then
sResult = Chr(65 + intColumnNumber)
ElseIf (intColumnNumber >= 26) Then
sResult = ColumnLetter(CLng(intColumnNumber \ 26)) _
& ColumnLetter(CLng(intColumnNumber Mod 26 + 1))
Else
err.Raise 8, "Column()", "Invalid Column #" & CStr(intColumnNumber + 1)
End If
ColumnLetter = sResult
End Function
Joseph のコードは優れていますが、VBA 関数を使用したくない、または使用する必要がない場合は、これを試してください。
n の値がセルにあると仮定します。 A2
この関数を使用します。
=MID(ADDRESS(1,A2),2,LEN(ADDRESS(1,A2))-3)
IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
これは 2 文字の列 (列まで) で機能します。 ZZ
)。3 文字の列に対して別の if ステートメントをネストする必要があります。
上記の数式は列では失敗します AY
, AZ
そして以下のそれぞれ nY
そして nZ
列。修正された式は次のとおりです。
=IF(COLUMN()>26,CHAR(ROUNDDOWN((COLUMN()-1)/26,0)+64)&CHAR(MOD((COLUMN()-1),26)+65),CHAR(COLUMN()+64)
wcmから:
VBAを使用したくない場合は、これを使用できます colnr を目的の番号に置き換えます
=MID(ADDRESS(1,colnr),2,LEN(ADDRESS(1,colnr))-3)
ADDRESS 関数を使用しているため、この数式は揮発性であることに注意してください。揮発性関数は、変更のたびに Excel によって再計算される関数です。通常、Excel は依存する参照が変更された場合にのみ数式を再計算します。
この式を使用すると、パフォーマンスが低下する可能性があります。
ここでは、VBScript バージョンから SQL Server 2000+ への変換を示します。
CREATE FUNCTION [dbo].[GetExcelColRef]
(
@col_seq_no int
)
RETURNS varchar(5)
AS
BEGIN
declare @Result varchar(5)
set @Result = ''
set @col_seq_no = @col_seq_no - 1
If (@col_seq_no >= 0 And @col_seq_no < 26)
BEGIN
set @Result = char(65 + @col_seq_no)
END
ELSE
BEGIN
set @Result = [dbo].[GetExcelColRef] (@col_seq_no / 26) + '' + [dbo].[GetExcelColRef] ((@col_seq_no % 26) + 1)
END
Return @Result
END
GO
Ruby のワンライナー:
def column_name_for(some_int)
some_int.to_s(26).split('').map {|c| (c.to_i(26) + 64).chr }.join # 703 => "AAA"
end
整数をbase26に変換してから分割し、計算を行って各文字をASCIIから変換します。最後に全員を元に戻します。除算、係数、再帰はありません。
楽しい。
これは MS Excel 2003 ~ 2010 では正常に動作します。をサポートする以前のバージョンで動作するはずです。 細胞(...)。住所 関数:
- 28番目の列については、
columnNumber=28
;Cells(1, columnNumber).Address
戻り値"$AB$1"
. - で分割を行うと、
$
符号は配列を返します。["","AB","1"]
- それで
Split(Cells(1, columnNumber).Address, "$")(1)
列名を与えます"AB"
.
アップデート:
' The following VBA function is just one way to convert column number
' values into their equivalent alphabetical characters:
Function ConvertToLetter(iCol As Integer) As String
Dim iAlpha As Integer
Dim iRemainder As Integer
iAlpha = Int(iCol / 27)
iRemainder = iCol - (iAlpha * 26)
If iAlpha > 0 Then
ConvertToLetter = Chr(iAlpha + 64)
End If
If iRemainder > 0 Then
ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
End If
End Function
に適用されます:Microsoft Office Excel 2007 SE / 2002 SE / 2000 SE / 97 SE
VBA コードが必要だと思います。
Public Function GetColumnAddress(nCol As Integer) As String
Dim r As Range
Set r = Range("A1").Columns(nCol)
GetColumnAddress = r.Address
End Function
これは VBA でやりたいことを実現します
Function GetNthExcelColName(n As Integer) As String
Dim s As String
s = Cells(1, n).Address
GetNthExcelColName = Mid(s, 2, InStr(2, s, "$") - 2)
End Function
これはvb.netで動作するようです
Public Function Column(ByVal pColumn As Integer) As String
pColumn -= 1
If pColumn >= 0 AndAlso pColumn < 26 Then
Return ChrW(Asc("A"c) + pColumn).ToString
ElseIf (pColumn > 25) Then
Return Column(CInt(math.Floor(pColumn / 26))) + Column((pColumn Mod 26) + 1)
Else
stop
Throw New ArgumentException("Invalid column #" + (pColumn + 1).ToString)
End If
End Function
私はジョセフのものを持ってきてBHにテストし、それから980-1000を与えたところ、良好に見えました。
VBA では、lCol が列番号であると仮定します。
function ColNum2Letter(lCol as long) as string
ColNum2Letter = Split(Cells(1, lCol).Address, "$")(0)
end function
これらの優秀な人々が投稿したコード サンプルはすべて問題ないようです。
注意すべきことが 1 つあります。Office 2007 以降、Excel には実際に最大 16,384 列があります。これは XFD に変換されます (以前の最大 256 列は IV でした)。これらのメソッドを 3 人のキャラクターに対して機能させるには、多少変更する必要があります。
そんなに難しくないはずですが...
これがゲイリー・ウォーターズの解決策です
Function ConvertNumberToColumnLetter2(ByVal colNum As Long) As String
Dim i As Long, x As Long
For i = 6 To 0 Step -1
x = (1 - 26 ^ (i + 1)) / (-25) - 1 ‘ Geometric Series formula
If colNum > x Then
ConvertNumberToColumnLetter2 = ConvertNumberToColumnLetter2 & Chr(((colNum - x - 1)\ 26 ^ i) Mod 26 + 65)
End If
Next i
End Function
経由 http://www.dailydoseofexcel.com/archives/2004/05/21/column-numbers-to-letters/
wcm (top value = xfd) のコメントを考慮すると、次のように計算できます。
function IntToExcel(n: Integer); string;
begin
Result := '';
for i := 2 down to 0 do
begin
if ((n div 26^i)) > 0) or (i = 0) then
Result := Result + Char(Ord('A')+(n div (26^i)) - IIF(i>0;1;0));
n := n mod (26^i);
end;
end;
アルファベットには 26 文字があり、16 進数や 2 進数と同様の数値体系があり、位置的に 26 の累乗を表す珍しい文字セット (A..Z) が使用されています。(26^2)(26^1)(26^0)。
参考までに、単一のステートメントとして序数 (ゼロベース) を指定して Excel 列名を指定する T-SQL です。
0 未満または 16,383 (Excel2010 の最大列数) を超える場合は、NULL を返します。
; WITH TestData AS ( -- Major change points
SELECT -1 AS FieldOrdinal
UNION ALL
SELECT 0
UNION ALL
SELECT 25
UNION ALL
SELECT 26
UNION ALL
SELECT 701
UNION ALL
SELECT 702
UNION ALL
SELECT 703
UNION ALL
SELECT 16383
UNION ALL
SELECT 16384
)
SELECT
FieldOrdinal
, CASE
WHEN FieldOrdinal < 0 THEN NULL
WHEN FieldOrdinal < 26 THEN ''
WHEN FieldOrdinal < 702 THEN CHAR (65 + FieldOrdinal / 26 - 1)
WHEN FieldOrdinal < 16384 THEN CHAR (65 + FieldOrdinal / 676 - 1)
+ CHAR (65 + (FieldOrdinal / 26) - (FieldOrdinal / 676) * 26 - 1)
ELSE NULL
END
+ CHAR (65 + FieldOrdinal % 26)
FROM TestData
ORDER BY FieldOrdinal
現在これを使用していますが、最適化できそうな予感がしています。
private String GetNthExcelColName(int n)
{
String firstLetter = "";
//if number is under 26, it has a single letter name
// otherwise, it is 'A' for 27-52, 'B' for 53-78, etc
if(n > 26)
{
//the Converts to double and back to int are just so Floor() can be used
Double value = Convert.ToDouble((n-1) / 26);
int firstLetterVal = Convert.ToInt32(Math.Floor(value))-1;
firstLetter = Convert.ToChar(firstLetterValue + 65).ToString();
}
//second letter repeats
int secondLetterValue = (n-1) % 26;
String secondLetter = Convert.ToChar(secondLetterValue+65).ToString();
return firstLetter + secondLetter;
}
=CHAR(64+COLUMN())