[[20250826105934]] 『26進数をアルファベットのみで作成する関数』(訓練中) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『26進数をアルファベットのみで作成する関数』(訓練中)

EXCELの列名のように、
A
B


Z
AA
AB


AZ
BA
BB


と行方向に26進数(アルファベットのみ)で作成したいです。

自分で調べたのですが、Base関数が近いかな?と思いネットで調べて勉強しました。
36進数で1〜Z、10〜19、1A〜1Z、20〜・・・となるものがありました。

そこで、A1セルに
「=BASE(ROW(), 36)」
と入力して、下方向にオートフィルしてみました。

結果
1
2
3


9
A
B


Z
10
11


19
1A
1B


となることはわかりました。
第二引数にn進数のnを入れてあげることで、
n進数に変換された戻り値を取得できることが理解できました。

こんな感じで、BASEをアルファベットのみの26進数になる関数を
調べてみたのですが、うまく検索できませんでした。

BASE関数でなくてもよいのですが、
イメージ的にはRANDARRAY関数の最小値と最大値を指定できれば・・
と思ったのですが、うまく検索ヒットできませんでした。

どなたか、以下のようになる方法をご存じでしたら
ご教授していただけないでしょうか。

よろしくお願いいたします。

A
B


Z
AA
AB


AZ
BA
BB


< 使用 Excel:Microsoft365、使用 OS:Windows11 >


 例えばA1セルに作成したい個数を入力するとして。

 =SUBSTITUTE(ADDRESS(1,SEQUENCE(A1,,1,1),4),1,"")
 ではどうだろうか?
 ADDRESS(1,SEQUENCE(A1,,1,1),4)
 で行番号が1で列が1からA1セルの数値までのアドレス(A1,B1,…Z1,AA1,AB1,…)を作成して
 SUBSTITUTE関数で行番号の1を消している。
(ねむねむ) 2025/08/26(火) 11:17:27

ご回答ありがとうございます。
おかげさまで希望通りできました。

SEQUENCE→連番の配列を作成する
ADDRESS→セル番地を求める
SUBSTITUTE→文字列を返還する

全て初めて知りました。
1つずつ分けて実行結果を確認することで
3つとも理解できました。

今後、練習、訓練をしてすべて実務レベルですぐに使えるよう努力します。
本当にありがとうございました。

(訓練中) 2025/08/26(火) 12:02:33


 ほぼ同じですが
 =TEXTSPLIT(ADDRESS(1,SEQUENCE(A1),2),"$")
(あ) 2025/08/26(火) 16:45:29

 別解を示してみます。
 アドレスを使わずに、26進法だけにこだわった手法です。

 ■名前定義を利用して再帰関数を定義する方法

 ColNameと言う名前で以下のブックベースの関数を定義します。
 =LAMBDA(n,
   IF(n=0,
      "",
      ColName(QUOTIENT(n-1,26)) & CHAR(65+MOD(n-1,26))
   )
 )
 そして、例えば
 =MAP(SEQUENCE(20000), ColName)
 とすれば、20,000個の文字列が作成されます。

 ■名前定義を使わずに、再帰関数を定義する方法(Z-combinator的手法)

 20,000個の配列を書き出すとして、名前定義を使わず、
 次のような関数で結果を返すことができます。

 =LET(
     gx,LAMBDA(x,
         Let(
             in,x,
             fx,LAMBDA(a,b,
                 IF(b=0,
                 "",
                 a(a,QUOTIENT(b-1,26)) & CHAR(65+MOD(b-1,26)))
             ),
             fx(fx,in)
         )
     ),
     MAP(sequence(20000),gx)
 )

(xyz) 2025/08/27(水) 08:51:04


アドレスを使う方法だと「XFD」までしか作れませんしね。
Microsoft365なら REGEXREPLACE関数を使えばいいです。

 =SCAN(9,SEQUENCE(20000),LAMBDA(x,y,REGEXREPLACE(BASE(DECIMAL(x,36)+1,36),"\d","A")
(d-q-t-p) 2025/08/27(水) 09:47:56

あ様
ご回答ありがとうございます。
TEXTSPLIT関数についても使えるよう訓練します。

xyz様
ご回答ありがとうございます。
ご回答いただいた2つの案ともに、
実行結果は2つとも思った通りになりましたが、
ちょっと理解するまでには時間がかかりそうです。
ご回答いただいたので、理解できるまで努力・訓練いたします。

d-q-t-p様
ご回答ありがとうございます。
コピペしたところ
「数式内の始めかっことおわりかっこが正しく対応していません」
とエラーが出てしまいます。
私が提案頂いた数式を理解できていないことが原因ですが、
こちらも理解できるまでは時間がかかりそうです。
ご回答いただいたので、理解できるまで努力・訓練いたします。

皆様、ご親切にご教授していただき
本当にありがとうございました。

(訓練中) 2025/08/27(水) 10:29:14


すみません。後ろの「))」が漏れていましたので付け足してください。
(d-q-t-p) 2025/08/27(水) 11:00:07

 いくつか補足しておきます。

 N進数を求めるアルゴリズムは以下とされているので、これを再現したものです。
 | N進数を求めるアルゴリズムは、求めたいN進数で割った余りを逆順に並べる方法です。
 | 具体的には、10進数をNで割り、商を次に割る数とし、その余りを記録します。
 | この操作を商が0になるまで繰り返し、出てきた余りを最後から順に並べると、N進数になります。
 ただし、使用する文字を0から始まるものではなく、A,B,C・・・・Zにするというものです。
 (char(65)は"A"です)

 繰返しは、"再帰"(自分自身を呼び出すこと)を利用している点が理解しにくいかもしれません。
 下記が参考になると思います。
https://excel-ubara.com/excel1/EXCEL671.html#sec06

 後者の方法は"出来ることはできる"ことを示そうというだけです。理解は不要です。
 最初の名前定義する方法を推奨します。実用的な方法です。

 なお、
 > BASE関数でなくてもよいのですが、
 > イメージ的にはRANDARRAY関数の最小値と最大値を指定できれば・・
 > と思ったのですが、うまく検索ヒットできませんでした。
 とのことでした。
 例えば、1から20000までの数値(整数)をランダムに12個とって、それをA〜Zの26進数表示し、
 3行4列の配列にしようとするなら、
    =MAP(RANDARRAY(3,4,1,20000,TRUE),ColName)
 とすれば良いことになります。

(xyz) 2025/08/28(木) 07:44:37


 xyzさんが書かれたリンク先の再帰の方法について。
LAMBDAをネストしないで再帰を実現することも可能です。
こんな感じですが、少しだけ速くなります。
=LET(F,LAMBDA(F,s,t,LET(y,INT((t-1)/26),
 w,CHAR(MOD(t-1,26)+65)&s,IF(y=0,w,F(F,w,y)))),
MAP(SEQUENCE(20000),LAMBDA(r,F(F,"",r))))

 再帰で定義された関数Fが使いにくいということで、別の関数Gを外側で定義すると次のようになります。
こうなるとxyzさんの式と同じことをしていて、速度も同じです。
=LET(F,LAMBDA(F,s,t,LET(y,INT((t-1)/26),
 w,CHAR(MOD(t-1,26)+65)&s,IF(y=0,w,F(F,w,y)))),
G,LAMBDA(u,F(F,"",u)),
MAP(SEQUENCE(20000),G))
(んなっと) 2025/08/29(金) 08:02:06

 5! (=FACT(5)=120)を再帰で求めるなら
=LET(F,LAMBDA(F,n,IF(n=1,1,n*F(F,n-1))),F(F,5))
覚え方は 「レフラフその他 イフ フフフフ」
(んなっと) 2025/08/29(金) 08:09:26

 投稿拝見しました。ありがとうございます。

 二つの式を並べてみると、
 最初の式では、
 MAPの第2引数の関数をLAMBDA(r,F(F,"",r)としていますが、
 それをいったん変数に束縛するかの違い、と考えてよいでしょうか。
 速度向上の原動力は何に由来するかがよくわかりませんでした。
 ご教示いただくとありがたいです。

 提示されたものは末尾再帰的なものにしているので早いということなんでしょうか。
 それなら二つとも私のものより早そうに思います。いかがでしょうか。
(xyz) 2025/08/29(金) 14:51:02

【1】
もう一度複数回試すと、「速度も同じです」は違っていましたね。無視してください。
LET(F,LAMBDA(F,  F(F, )) で再帰の定義は完結しているというのが主題です。

【2】
引数の数を減らす以下の2つは同じことで、わざわざ使うほどのことではないと思います。
・上の式の外側にもう一つ別の関数を追加する(私の2番目の式)
・LAMBDAをネストさせてもう一つの関数を追加する(xyzさんの式)
※ただし、イータ縮小ラムダの記述ができるようになるのは長所。
(んなっと) 2025/08/29(金) 15:41:14


あと末尾再帰になっているから速いというのはその通りなのかもしれませんが、
「ワークシート関数での再帰関数の書き方」という本筋とは無関係です。
速度のことは書かなければよかったですね。混乱させて申し訳ありませんでした。
以後気を付けます。

(んなっと) 2025/08/29(金) 15:47:55


丁寧なご返答ありがとうございました。引き続き勉強材料にさせていただきます。

(xyz) 2025/08/29(金) 16:17:54


ExcelとVBAで列番号を最速で相互変換する関数を求めて徹底調査してみた - えくせるちゅんちゅん
https://www.excel-chunchun.com/entry/2019/02/08/020935

 ▼引用
 > 真っ先にエクセルの列番号はA〜Zの26進数かと考えますが、
 > 実は最上位の桁には空白があるため27通りあります。
 > では27進数かと思いきや下位の桁は十進数の0に相当する空白が無いんですよね。

 私もこれにハマって途中でブン投げてしまったクチですね。 

 そこがメインの内容ではございませんが、読み物として面白かったんで、
 本トピの関連記事としてご紹介しておこうかと... ^^;

(白茶) 2025/08/29(金) 23:13:54


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.