TSabcで、エクセルの列番号(A-Z,AA-ZZ,..)を 数(1-)に変換する話題が出ています。
Icon版で、変換プログラムとその逆変換(1- -> A-Z,AA-..)ポストしておきました。
ord(文字->数 変換関数),char(数->文字 変換関数)を使ったものです。
他の言語で作成されたのを見ますと、文字列 "A-Z"へのインデックスで実現なさって
いる例がありましたので、Icon版でもインデックス方式で書いてみましょう。
Iconでは、文字に関する組込キーワードとして、
&ucase : 英大文字セット 'AB..Z'
&lcase : 英小文字セット 'ab..z'
&letters : 英大文字+英小文字セット 'AB..Zab..z'
&digits : 数字セット '0123456789'
&ascii : ascii文字セット (128種)
&cset : (1バイト)全文字セット (256種)
が、用意されています。
このキーワードは、(1バイト)文字の集合(cset)ですが、Iconでは 文字列として
扱う文脈では、文字列に変換して扱ってくれます。
文字列に変換された場合の並びは、コードの若番順です。
!ucase等で、順に取り出す場合も、若番順に出てきますので、特にソートを掛ける
必要はありません。
今回は、英大文字セット &ucaseを使います。 この &ucaceを文字列として扱って
そのインデックスを使う方式だと、こういう procedureになります。
-----^ EX2N.ICN ( date:03-10-23 time:22:57 ) ---------------<cut here
####################
# エクセル風列番号(A-Z,AA-ZZ,..) <-> 数(1- )
####################
# ex2n.icn Rev.1.1 2003/10/23 風つかい
# TSabcの話題
# 英大文字列(&ucase)へのインデックス方式
# This file is in the public domain.
####################
# Excel風列番号(A-Z,AA-ZZ,..) -> 数(1- )
####################
# n := i1*26^0 +i2*26^1 +i3*26^2 ... (i1-末尾から A-Zを 1-26へ変換した数)
procedure excel2n(s)
n := 0 # 英大文字↓ # ↓文字→数変換
every n +:= ( &ucase ? upto(s[i := *s to 1 by -1])) * (26^(i-1))
# ↑ nに足し込む ↑*s〜 1 generator sの末尾から順に
return n
end
####################
# 数(1-) -> Excel風列番号(A-Z,AA-ZZ,..)
####################
procedure n2excel(n)
s := "" # 変換文字足し込みバッファー
while n > 0 do { # 26で割れる限り
n1 := (n - 1) /26 # 26で割った余りを 1〜26にするため -1して、後で +1
n2 := n - n1*26 # 最下位桁(1〜26) # (n-1) -n2*26 +1
s := &ucase[n2] || s # 文字へ変換し sの前側に足し込む
n := n1 # 次の桁の計算に nを更新
}
return s
end
-----$ EX2N.ICN ( lines:32 words:136 ) ---------------------<cut here
サンプル文字列を変換するこんなプログラムを linkしてみます。
-----^ EXCEL2.ICN ( date:03-10-23 time:22:59 ) -------------<cut here
####################
# エクセル風列番号(A-Z,AA-ZZ,..) <-> 数(1- )
####################
# Excel2.icn Rev.1.1 2003/10/23 風つかい
# TSabcの話題
# This file is in the public domain.
link ex2n
procedure main()
# テストデータ
L := ["A","Z", # Z:26^1
"AA","ZZ", # ZZ:26^2+26^1
"AAA","ZZZ", # ZZZ:26^3+26^2+26^1
"AAAA","ZZZZ", # ZZZZ:26^4+26^3+26^2+26^1
"AAAAA","ZZZZZ", # ZZZZZ:26^5+26^4+26^3+26^2+26^1
"AAAAAA","ZZZZZZ"] # ZZZZZZ:26^6+26^5+26^4+26^3+26^2+26^1
# 動作テスト
every s := !L do {
# 変換
writes(s," -> ",n := excel2n(s))
# 逆変換
write(" -> ",n2excel(n))
}
end
-----$ EXCEL2.ICN ( lines:25 words:70 ) --------------------<cut here
動かすとこうなります。
-----^ EXCEL2.1 ( date:03-10-23 time:22:59 ) ---------------<cut here
A -> 1 -> A
Z -> 26 -> Z
AA -> 27 -> AA
ZZ -> 702 -> ZZ
AAA -> 703 -> AAA
ZZZ -> 18278 -> ZZZ
AAAA -> 18279 -> AAAA
ZZZZ -> 475254 -> ZZZZ
AAAAA -> 475255 -> AAAAA
ZZZZZ -> 12356630 -> ZZZZZ
AAAAAA -> 12356631 -> AAAAAA
ZZZZZZ -> 321272406 -> ZZZZZZ
-----$ EXCEL2.1 ( lines:12 words:60 ) ----------------------<cut here
ところで、エクセルの列番号は、A-Zの文字から1文字、2文字、..と組み合わせ
た重複順列と同じですね。
エクセルの列番号は、重複順列生成 generatorで作り出せます。 エクセルでは列は
256迄しかないそうですので、256個限定生成とします。
-----^ EXCEL3.ICN ( date:03-10-23 time:23:01 ) -------------<cut here
####################
# エクセル風列番号生成 256個限定
####################
# Excel3.icn Rev.1.1 2003/10/23 風つかい
# This file is in the public domain.
link lineg, # lineg 1行整形 generator # 秋の夜長は Iconでも(5)
msperm # msperm 重複順列生成 generator # 秋の夜長は Iconでも(5)
procedure main()
write("mspermで エクセル風列番号を 256個生成")
# 英大文字 cset↓ 生成数限定↓ ↓linegストッパー
every write(lineg(,,left(msperm(&ucase,1 to 26) \256,2) | &null))
# 左寄せ桁合わせ↑ ↑数 1〜26 generator
end
-----$ EXCEL3.ICN ( lines:14 words:58 ) --------------------<cut here
動かすとこうなります。
-----^ EXCEL3.1 ( date:03-10-23 time:23:01 ) ---------------<cut here
mspermで エクセル風列番号を 256個生成
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
AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ AR AS AT AU AV AW AX AY AZ
BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BR BS BT BU BV BW BX BY BZ
CA CB CC CD CE CF CG CH CI CJ CK CL CM CN CO CP CQ CR CS CT CU CV CW CX CY CZ
DA DB DC DD DE DF DG DH DI DJ DK DL DM DN DO DP DQ DR DS DT DU DV DW DX DY DZ
EA EB EC ED EE EF EG EH EI EJ EK EL EM EN EO EP EQ ER ES ET EU EV EW EX EY EZ
FA FB FC FD FE FF FG FH FI FJ FK FL FM FN FO FP FQ FR FS FT FU FV FW FX FY FZ
GA GB GC GD GE GF GG GH GI GJ GK GL GM GN GO GP GQ GR GS GT GU GV GW GX GY GZ
HA HB HC HD HE HF HG HH HI HJ HK HL HM HN HO HP HQ HR HS HT HU HV HW HX HY HZ
IA IB IC ID IE IF IG IH II IJ IK IL IM IN IO IP IQ IR IS IT IU IV
-----$ EXCEL3.1 ( lines:11 words:259 ) ---------------------<cut here
すると、こんなやりかたもアリですね〜。 この文字列と生成順番号をテーブルに
登録しておけば、テーブル参照で 変換も逆変換 もできますね。
これだと、変換や逆変換の計算 を考えなくて済みますね。
-----^ EXCEL4.ICN ( date:03-10-23 time:23:02 ) -------------<cut here
####################
# エクセル風列番号(A-Z,AA-IV)
####################
# Excel4.icn Rev.1.1 2003/10/23 風つかい
# This file is in the public domain.
link msperm # msperm 重複順列生成 generator # 秋の夜長は Iconでも(5)
procedure main()
# 変換テーブル生成
Ts2n := table() # 空 table生成
Tn2s := table() # 空 table生成
# table登録
n := 0 # 生成順番号
# ↓順列生成 generator ↓生成数制限(256個)
every ss := msperm(&ucase,1 to 26) \256 do {
# ↑数列 1〜26 generator
Ts2n[ss] := (n +:= 1) # 文字->数 tableに登録
Tn2s[n] := ss # 数->文字 tableに登録
}
# テストデータ生成 ↓これは参照エラー(257個目なので)
L := ["A","B","Y","Z","AA","AB","IV","IW"]
# 変換結果書き出し
every s := !L # ↓tableに無ければ 値は "ERR"
do write(s," -> ",n := \Ts2n[s] | "ERR"," -> ",\Tn2s[n] | "ERR")
# ↑tableに無ければ 値は "ERR"
end
-----$ EXCEL4.ICN ( lines:31 words:114 ) -------------------<cut here
動かすとこうなります。
-----^ EXCEL4.1 ( date:03-10-23 time:23:02 ) ---------------<cut here
A -> 1 -> A
B -> 2 -> B
Y -> 25 -> Y
Z -> 26 -> Z
AA -> 27 -> AA
AB -> 28 -> AB
IV -> 256 -> IV
IW -> ERR -> ERR
-----$ EXCEL4.1 ( lines:8 words:40 ) -----------------------<cut here
風つかい(hshinoh@...)
IconのWWWは、 http://www.cs.arizona.edu/icon/
UniconのWWWは、http://unicon.sourceforge.net/index.html
BGM: Jazz Sebastien Bach / les Swingle Singers