作者: Hiroshi Shinohara
日時: 2003/10/23(23:29)
  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