ゴルフの一般的なヒントは何VBA
ですか?私は、少なくともある程度特定のゴルフ問題全般のコーディングに適用できるアイデアを探していますVBA
(たとえば、「コメントの削除」は答えではありません)。回答ごとに1つのヒントを投稿してください。
私は他の言語で仕事をしてきましたが、私はで最も強く、このサイトでVBA
使用VBA
しているゴルファーはあまりいません。
ゴルフの一般的なヒントは何VBA
ですか?私は、少なくともある程度特定のゴルフ問題全般のコーディングに適用できるアイデアを探していますVBA
(たとえば、「コメントの削除」は答えではありません)。回答ごとに1つのヒントを投稿してください。
私は他の言語で仕事をしてきましたが、私はで最も強く、このサイトでVBA
使用VBA
しているゴルファーはあまりいません。
回答:
ByRef
呼び出すときにデフォルトを活用するいくつかの追加文字を保存するために、aのSub
代わりに呼び出しを使用することも可能Function
です...
これ(87文字)
Sub a()
b = 0
Do Until b = 5
b = c(b)
Loop
End Sub
Function c(d)
c = d + 1
End Function
再加工可能( 73文字)に変更:
Sub a()
b = 0
Do Until b = 5
c b
Loop
End Sub
Sub c(d)
d = d + 1
End Sub
これは永久にループしないことに注意してください。ただし、b
値を再割り当てすることはないようです。
上記は使用しません Function
呼び出しをが、代わりに呼び出しのByRef
(「参照による」)機能を利用しSub
ます。これが意味することは、渡された引数が呼び出し側関数と同じ変数であることです(ByVal
コピーである「値渡し」とは対照的です)。渡された変数の変更は、呼び出し元の関数に変換されます。
デフォルトでは、 vbaはすべての引数をとして取得ByRef
するため、これを定義するために文字を使用する必要はありません。
上記の例は、関数の戻り値によっては、完全に変換されない場合があります。(つまり、渡されたものとは異なるデータ型を返す)が、これにより、元の変数を変更しながら、戻り値を取得することもできます。
例えば:
Sub a()
b = 0
Debug.Print c(b) ' This will print 0, and b will equal 1.'
End Sub
Function c(d)
c = d
d = d + 1
End Function
イミディエイトウィンドウは、有効なVBA実行可能ステートメントを評価します。コードエディタの場合と同様に、イミディエイトウィンドウにステートメントを入力するだけです。VBAコードをすばやく実行し、次の理由で多くの追加文字を保存できます。
ここではVBAコードの例は、タグ付きPPCGのポストに答えるために、イミディエイトウィンドウにあるコードゴルフを:Aせずに手紙A
?Chr(88-23);
ジョファンが答えた。
クレジット画像: Excel Campus
a="value":?a
最初にの値を設定してからa
、印刷します。
一部の条件付きチェックは、ループと組み合わせて使用すると冗長です。たとえば、For
、開始条件が実行条件の範囲外にある場合、ループは処理されません。
言い換えれば、これ(49文字):
If B > 0 Then
For C = A To A + B
'...
Next
End If
これに変換できます(24文字):
For C = A To A + B ' if B is 0 or less, then the code continues past Next, unabated.
'...
Next
VBAのほとんどの場合、Option Explicit
省略して(とにかくデフォルトで省略されることがよくあります)、スキップできますDim
ます。
そうすることで、これ(96文字):
Option Explicit
Sub Test()
Dim S As String
Dim S2 As String
S = "Test"
S2 = S
MsgBox S2
End Sub
これになります(46文字):
Sub Test()
S = "Test"
S2 = S
MsgBox S2
End Sub
特定のオブジェクト(配列など)を使用する必要がある場合、Dim
その変数が必要になる場合があります。
Evaluate()
そして []
前に指摘したように、ハードコードされた範囲呼び出しは、角括弧[A1]
表記を使用して減らすことができます。ただし、それだけでなく、多くの用途があります。
MSDNドキュメントによると、このApplication.Evaluate()
メソッドは、Name
Microsoft Excelの命名規則で定義されているように、1つの引数を取ります。
NB [string]
は短縮形ですEvaluate("string")
(""
文字列データ型を示す音声マークに注意してください)。ただし、最後にいくつかの重要な違いがあります。
それで、それは使用の面で何を意味しますか?
基本的[some cell formula here]
に、Excelワークシート内のセルを表します。通常のセルでできることは何でも入力できます。
要約すると、例付き
[B7]
そのセルへの参照を返します?[B7].Address
リターン"B$7$"
[A1:B5]
A1:B5
(Range)への範囲参照を返します[A1:B5 A3:D7]
A3:B5
(Intersect)への範囲参照を返します[A1:B5,C1:D5]
A1:D5
(技術的にA1:B5,C1:D5
)(Union)への範囲参照を返します[myRange]
A1:G5を参照するなどのユーザー定義[Table1]
(おそらくcodegolfにはあまり役に立たない)Evaluate()
または[]
[SUM(1,A1:B5,myRange)]
ここでmyRangeの範囲の値の算術和を返します。ここではVBA変数ではなくワークブック名を指します[IF(A1=1,"true","false")]
(vbaの同等物より1バイト短いIif([A1]=1,"true","false")
)[CONCAT(IF(LEN(A1:B7)>2,A1:B7&" ",""))]
-長さが2を超える範囲のすべての文字列をスペースで結合します!
演算子を使用して、セルまたは別のブックで定義された名前を参照できます。[[BOOK1]Sheet1!A1]
BOOK1のA1への範囲参照を返すか['[MY WORKBOOK.XLSM]Sheet1!'A1]
、MY WORKBOOK
'
名前にスペースが含まれているワークブックの場合、およびデフォルトの名前付きワークブックの拡張子がないことに注意してください(BOOK+n
)NBこの情報についてSOで質問をしたので、より良い説明のためにそこを見てください
入ってくるものと同様に、出てくるものには、ワークシートのセルが返すことができるものが含まれます。これらは、標準のExcelデータ型(およびそれに相当するVBA)です。
Boolean
)String
)Double
)Variant/Error
)(これらは非破壊エラーです。つまり、コードの実行を停止せず、?[1/0]
正常に実行されます)ただし、セルでは返せない返される可能性のあるものがいくつかあります。
Range
)(上記のセクションを参照)Variant()
)既に示したよう[]
に、標準のExcelデータ型の1つを返す配列数式を評価するために使用できます。たとえば、[CONCAT(IF(LEN(A1:B7)>2,A1:B7&" ",""))]
どちらが返されますText
。ただしEvaluate
、Variant
型の配列を返すこともできます。これらは
ハードコーディング:
[{1,2;3,4}]
-2D配列を出力します。,
列セパレーターであり、;
行を分離します。1D配列を出力できます
配列式:
[ROW(A1:A5)]
-出力する2次元アレイを{1,2,3,4,5}
(2,1)は、第2のアイテム(まだいくつかの機能出力1Dアレイ)、すなわち、
[LEN(A1:A5)]
範囲の最初のセルのテキストの長さのみを出力します
Split([CONCAT(" "&LEN(A1:A5))])
最初のアイテムが空である0から5までの1D配列を与える
[INDEX(LEN(A1:A5),)]
別の回避策は、基本的に配列処理関数を使用して、目的の配列を返す動作を取得する必要RAND()
があります。
Evaluate()
対 []
との間にはいくつかの違いがEvaluate()
あり[]
ます
Evaluate("SUM(B1,1,"&v &",2)")
合計う[B1]
、1
、2
および変数v
配列
配列を返す場合、Evaluateのみが配列インデックスと共に使用できます。
v=Evaluate("ROW(A1:A5)")(1,1) ''#29 bytes
に等しい
i=[ROW(A1:A5)]:v=i(1,1) ''#23 bytes
i=[ROW(A1:A5)]:v=i(2,1):?v
Next
ステートメントを組み合わせるNext:Next:Next
まで凝縮される可能性があります
Next k,j,i
どこのためのイテレータFor
ループがありi
、j
とk
-の順で。
たとえば、以下(69バイト)
For i=0To[A1]
For j=0To[B1]
For k=0To[C1]
Debug.?i;j;k
Next
Next
Next
65バイトまで圧縮可能
For i=0To[A1]
For j=0To[B1]
For k=0To[C1]
Debug.?i;j;k
Next k,j,i
そして、これが書式設定とインデントにどのように影響するかについては、これを処理するための最良のアプローチは、次のステートメントを最も外側のforステートメントに揃えることです。例えば。
For i=0To[A1]
For j=0To[B1]
For k=0To[C1]
Debug.?i;j;k
Next k,j,i
If
ステートメントの削減条件を使用して変数を割り当てる場合 If ... Then ... Else
チェックEnd If
、チェック全体を1行に配置することを排除することにより、使用するコードの量を減らすことができます。
たとえば、これ(37文字):
If a < b Then
c = b
Else
c = a
End If
これに減らすことができます(30文字)
If a < b Then c = b Else c = a
ネストされた条件が複数ある場合は、次の方法でも最小化できます。
If a Then If b Then If c Then Z:If d Then Y:If e Then X Else W Else V:If f Then U 'Look ma! No "End If"!
に注意してください :
により、If
ブロック内に複数の行/コマンドを追加できます。
このような単純なケースでは、通常Else
、If
チェックの前に変数を設定することで(25文字)を削除することもできます。
c = a
If a < b Then c = b
さらに良いことに、IIf()
関数(20文字)を使用して、上記をさらにこれに減らすことができます。
c = IIf(a < b, b, a)
Range("A1")
呼び出しを減らして好きRange("A1").Value
(17バイト)およびより単純なRange("A1")
(11バイト)は[A1]
(4バイト)に減らすことができます
[]
置換の使用Evaluate()
は、単なる範囲呼び出しよりもはるかに用途が広いです。例えば、あなたは交換し、それを使用することができますWorksheetFunction.FuncName(args)
だけで[FuncName(args)]
、このような?[SUMPRODUCT({1,3,5},{2,7,-1})]
または非常に便利[MIN(1,2,3)]
/[MAX(1,2,3)]
Evaluate("str")
または速記[str]
はVBAで非常に強力です。最近発見したばかりで、ゴルフにも役立つと思います。
VBAは、実際には必要のない多くのスペースを追加するように自動フォーマットします。メタについての答えがあります。これは、なぜ自動フォーマットによって追加されたバイトを割引できるのか、非常に理にかなっています。ただし、削除しすぎていないことを常に確認することが重要です。例として、スペースを削除するだけでほぼ22%削減された私の答えを次に示します。
元のバージョン:(188バイト)
Sub g(n)
For i = 0 To 1
For x = -3 To 3 Step 0.05
y = n ^ x * Cos(Atn(1) * 4 * x)
If y < m Then m = y
If i = 1 Then Cells(500 * (1 - y / m) + 1, (x + 3) * 100 + 1) = "#"
Next
Next
End Sub
削減バージョン:(146バイト)
Sub g(n)
For i=0To 1
For x=-3To 3Step 0.05
y=n^x*Cos(Atn(1)*4*x)
If y<m Then m=y
If i=1Then Cells(500*(1-y/m)+1,(x+3)*100+1)="#"
Next
Next
End Sub
縮小バージョンをコピーしてVBAに貼り付けると、自動的に元のバージョンに展開されます。スペースを削除するのに有効な場所で遊んでください。私がこれまでに見つけたものはすべて、VBAが特定のコマンドを表示すると予想されるパターンに従っているようです。これがないと、VBAは有効なコードではないからです。ここに私がこれまでに見つけたものをいくつか示します:
+-=/*^
などTo
とStep
中For
:For x=-3To 3Step 0.05
To
、&
、Then
、等)このような数値リテラルが先行なら)
、?
、%
、等&
文字列を結合した後:Cells(1,1)=Int(t)&Format(t,":hh:mm:ss")
If s=StrReverse(s)Then
Replace(Space(28)," ",0)
?
vsのようなものPrint
は受け入れられますが&
、変数の直後のように型宣言を置くことは、例えばDebug.?a&"z"
与えDebug.Print a&; "z"
ます。;
追加文字は、実行するためにコードのために不可欠である-これはまだ許可されていますか?
If i=1 Then
になることがありIf i=1Then
、原則としてリテラルを次の予約語は、数は、ということが、あるため)
、?
、%
、...など、Aによって分離する必要はありません。スペース
)
(またはその他の非数字リテラル)と&
ピクセルアートは、キャンバスを構築する必要がないため、Excelの最も強力な領域の1つです。既に存在しているので、必要なことは少し調整するだけです。
Cells.RowHeight=48
または、代わりに、1バイト以上、ただしはるかに使いやすい
Cells.ColumnWidth=2
をRange
呼び出すことで、任意のオブジェクトを色付けできます
`MyRangeObj`.Interior.Color=`ColorValue`
注:これは、このwikiに記載されている他のトリック[]
(たとえば[A1:R5,D6]
、a Cells(r,c)
またはa の使用よりも表記法(たとえば)を使用して範囲を参照するなど)と組み合わせることができます。Range(cellAddress)
ます。 callます。さらに、このウィキに記載されているように、これを負のカラー値と組み合わせて、カラーリファレンスのサイズを小さくすることができます
範囲参照
セルA1
は、次のいずれかの方法で参照できます。
Range("A1")
Cells(1,1)
[A1]
範囲A1:D4
は次のいずれかの方法で参照できます
Range("A1:D4")
Range("A1").Resize(4,4)
Cells(1,1).Resize(4,4)
[A1].Resize(4,4,)
[A1:D4]
カラーリファレンス
Black 0
White -1
Red 255
Aqua -256
特定の関数を頻繁に使用する場合は、それらをユーザー定義関数に再割り当てしてください。
次のコード(127文字)は、次のものから削減できます。
Sub q()
w = 0
x = 1
y = 2
z = 3
a = Format(w, "0.0%")
b = Format(x, "0.0%")
c = Format(y, "0.0%")
d = Format(z, "0.0%")
End Sub
〜(124文字):
Sub q()
w = 0
x = 1
y = 2
z = 3
a = f(w)
b = f(x)
c = f(y)
d = f(z)
End Sub
Function f(g)
f = Format(g, "0.0%")
End Function
これとByRefトリックを組み合わせると、さらに多くの文字(114まで)を保存できます。
Sub q()
w = 0
x = 1
y = 2
z = 3
a = f(w)
b = f(x)
c = f(y)
d = f(z)
End Sub
Sub f(g)
g = Format(g, "0.0%")
End Sub
VBAはを定義するために多くの文字を使用するため、慎重にこれを実行してくださいFunction
。2番目のコードブロックは、実際にして第一よりも大きいであろう任意の数の少ないFormat()
コール。
a = f(w)
ように減らすことができますf w
入力変数を介したSub
ルーチンおよびFunction
sへの入力
Public Sub A(ByRef B as String)
に減少する可能性があります
Sub a(b$)
通話は、VBAのデフォルトのため、暗黙的であり、(ほぼ)常にドロップすることができます。Public
ByRef
型リテラルは$
強制的b
に型になりString
ます。
その他の型リテラル
!
シングル@
通貨#
ダブル%
整数$
ストリング&
長いです^
LongLong(64ビットのみ)さらに、入力変数をデフォルトの型のVariant
ままにして、型ベースのエラーを未処理のままにしておくことも一般的に受け入れられています。例えば。Sub E(F)
どのF
タイプであると予想されますかBoolean[]
(これはのようなルーチンに渡されますE Array(True, False, False)
)
Sub
経由のルーチンおよびイミディエイトウィンドウ関数への入力Cells
VBAには完全に機能するコンソールがないため、公式の STDIN がないため、入力を渡すことである程度プレイすることができます。
Excelでは、セルまたはセルの範囲から入力を受け取ることが一般的に受け入れられています。
s=[A1]
.value
から暗黙的にセルを配置します[A1]
(cells(1,1)
またはとして参照される場合もありますrange("A1")
問題の例:メッセージボックスに入力を表示する
サブルーチン経由 Sub A:msgbox[A1]:End Sub
イミディエイトウィンドウ機能を介して msgbox[A1]
条件付きコンパイル引数による入力
VBAプロジェクトは、コマンドラインまたはVBAProjectのプロパティからの引数の取得をサポートしています(プロジェクトエクスプローラー-> [VBAプロジェクト]-(右クリック)-> VBAProjectのプロパティ->条件付きコンパイル引数を使用して表示)
これは主にエラーコードチャレンジに役立ちます
条件付きコンパイル引数n=
[some_value]を指定すると、の値に基づいてエラーコードを生成するコードを実行できますn
。n=
VBAProjectのプロパティペインの条件付きコンパイル引数セクションで、コードに2バイトを追加する必要があることに注意してください。
サンプルコード
...
#If n=3 then
return '' Produces error code '3', Return without GoSub
#ElseIf n=20 then
resume '' Produces error code '20', Resume without Error
#EndIf
...
経由関数値の出力
ここで言うまでもありませんが、以下に引用する一般的な形式は、作成できる限りコンパクトです。
Public Function A(b)
...
A=C
End Function
注:ほとんどの場合、メソッドをサブルーチンに変換してVBEイミディエイトウィンドウに出力するバイト数が増えます(以下を参照)
VBEイミディエイトウィンドウを介したSub
ルーチンおよびFunction
s からの出力
VBEイミディエイトウィンドウ(別名VBEデバッグウィンドウ)への出力は、テキストベースのチャレンジに対するVBAの一般的な出力方法ですが、Debug.Print "Text"
呼び出しが実質的にゴルフにかけられる可能性があることを覚えておくことが重要です。
Debug.Print "Text"
機能的に同じです
Debug.?"Text"
として?
のオートフォーマットPrint
。
Sub
他のメソッドを介したルーチンおよびVBEイミディエイトウィンドウ関数からの出力
まれな状況がちょうどいいときに時々 、あなたは、フォントサイズの調整、フォント選択、およびズームなどのVBAで利用できる多くの些細な入力の一部から入力を取ることがあります。(例:Wordフォントサイズセレクターのエミュレート)
StackExchangeは、使用しているため記法とPrettify.jsを、一般的にそれらをより専門的に見えるあなたのコーディングの答えに言語フラグを追加することが可能です。これがVBAでのゴルフをより良くすることを保証することはできませんが、あなたがあなたのように見えるようにすることは保証できます。
以下のフラグのいずれかを追加すると、変換されます
Public Sub a(ByRef b As Integer) ' this is a comment
に
Public Sub a(ByRef b As Integer) ' this is a comment
VBA言語タグ
<!-- language: lang-vb -->
<!-- language-all: lang-vb -->
注:後者は回答内のすべてのコードセグメントを変換しますが、前のコードは直後のコードセグメントのみを変換します
lang-vb
え?-不思議なことに、lang-vba
VBAの回答よりも形式が優れている。
lang-vba
強調表示を提供しますが、実際には単なるデフォルトの強調表示だからです。どうやらVBAはPrettify.jsに実際には実装されていないため、VBの強調表示に固執する必要があります
If .. Then
チェック他の言語のように、複数If
のチェックは、通常の使用を可能にする、単一ラインに組み合わせることができるAnd
/ Or
(即ち&&
/ ||
VBAにAの両方置き換え、Cなどで)Then
とEnd If
。
たとえば、ネストされた条件(93文字)の場合:
'There are MUCH easier ways to do this check (i.e. a = d).
'This is just for the sake of example.
If a = b Then
If b = c Then
If c = d Then
MsgBox "a is equal to d"
End If
End If
End If
(69文字)になります:
If a = b And b = c And c = d Then
MsgBox "a is equal to d"
End If
これは、ネストされていない条件でも機能します。
検討(84文字):
If a = b Then
d = 0
End If
If c = b Then
d = 0
End If
これは(51文字)になります:
If a = b Or c = b Then
d = 0
End If
d=iif(a=b or c=b,0,d)
For
ループ使用するとき For
ループする場合、Next
行には変数名は必要ありません(通常のコーディングで使用する方がおそらく良いでしょう)。
したがって、
For Variable = 1 to 100
'Do stuff
Next Variable
以下に短縮できます。
For Variable = 1 to 100
'Do stuff
Next
(節約量は変数名によって異なりますが、ゴルフをしている場合は、おそらく1文字+ 1スペースです。)
文字列を個々の文字に分割すると便利な場合もありますが、VBAで手動でこれを行うには少しのコードが必要になる場合があります。
ReDim a(1 To Len(s))
' ReDim because Dim can't accept non-Const values (Len(s))
For i = 1 To Len(s)
a(i) = Mid(s, i, 1)
Next
代わりに、1行の比較的最小限の関数チェーンを使用してジョブを完了できます。
a = Split(StrConv(s, 64), Chr(0))
これにより、文字列s
がVariant
配列に割り当てられますa
。ただし、配列の最後の項目は空の文字列(""
)であり、適切に処理する必要があるため、注意してください。
仕組みは次のとおりです。StrConv
関数はString
を指定した別の形式にます。この場合、64 = vbUnicode
であるため、Unicode形式に変換されます。単純なASCII文字列を処理する場合、結果はnull文字(空の文字列ではなく、""
各文字の後に挿入され)です。
以下 Split
String
、ヌル文字を使用して、結果を配列に変換しますChr(0)
を区切りとして。
Chr(0)
空の文字列と同じではないことに注意することが重要です""
使用Split
して""
も、予想される配列は返されません。同じことが当てはまりますvbNullString
(ただし、ゴルフをしている場合、なぜこのような冗長な定数を最初に使用するのでしょうか?)。
With
(時々!脚注を参照)を使用して With
、あなたが繰り返しいくつかのオブジェクトを使用する場合のステートメントは、大幅にコードサイズを小さくすることができます。
すなわち、これ(80文字):
x = foo.bar.object.a.value
y = foo.bar.object.b.value
z = foo.bar.object.c.value
(79文字)としてコーディングできます:
With foo.bar.object
x = .a.value
y = .b.value
z = .c.value
End With
上記は最良のシナリオでさえありません。Access内からApplication
など、で何かを使用する場合Excel.Application
、改善はより重要になります。
*状況に応じて、With
これより効率的な場合とそうでない場合があります(64文字):
Set i = foo.bar.object
x = i.a.value
y = i.b.value
z = i.c.value
交換を検討
Do While a<b
'...
Loop
または
Do Until a=b
'...
Loop
時代遅れだがバイト数が少ない
While a<b
'...
Wend
Sub
またはをFunction
途中で終了する必要がある場合は、代わりにExit ...
For i=1To 1000
If i=50 Then Exit Sub
Next
考える End
For i=1To 1E3
If i=50 Then End
Next
End
すべてのコード実行を停止し、グローバル変数をクリアすることに注意してください。
For
とEnd
する場合があることを反映するために)100
会ったことはありませんとに、不要なバイト追加
Debug.Print
してPrint
電話するDebug.Print [some value]
(12バイト。末尾のスペースに注意してください)は、
Debug.?[some value]
(7バイト。末尾のスペースがないことに注意してください)。
同様に、
Print
(6バイト)に減らすことができます
?
(1バイト)。
さらに、匿名VBEイミディエイトウィンドウ関数のコンテキストで操作する場合、Debug
ステートメントは完全に削除され、代わりにVBEイミディエイトウィンドウへの印刷は?
STDIN / STDOUTであると想定される場合があります。
文字列を印刷するとき、の代わりに特殊文字を使用することもできます&
。これらは、印刷されたものまたは空白の除去の代替フォーマットを可能にします
代わりに変数文字列を結合するには
Debug.Print s1 &s2
セミコロンを使用できます ;
Debug.?s1;s2
このセミコロンは、あいまいさがない限り、連続する文字列のデフォルトの動作です。したがって、これらは有効です。
Debug.?s1"a"
Debug.?"a"s1
だがしかし
Debug.?s1s2 'as this could be interpreted as a variable named "s1s2", not 2 variables
'use Debug.?s1 s2 instead (or s1;s2)
Debug.?"a""b" 'this prints a"b, so insert a space or ; for ab
注意してください; デフォルトでは改行が印刷のたびに追加されるため、行末で改行が抑制されます。VBAコードによって返されたバイトのカウントは議論中です
タブで結合するには、コンマを使用します,
(実際には14スペースですが、に応じて)
Debug.?s1,s2 'returns "s1 s2"
最後に、型宣言を使用して、;の代わりに文字列を結合できます。それぞれが書式設定にわずかな影響を及ぼします。以下a = 3.14159
はすべて最初の行です
Debug.?a&"is pi" -> " 3 is pi" 'dims a as long, adds leading and trailing space to a
Debug.?a!"is pi" -> " 3.14159 is pi" 'dims a as single, adds leading and trailing space
Debug.?a$"is pi" -> "3.14159is pi" 'dims a as string, no spaces added
Array()
Choose()
Select
またはのIf...Then
別の変数の値に基づいて変数を割り当てる場合If...Then
、次のようにチェック付きでステップを書き出すのが理にかなっています。
If a = 1 Then
b = "a"
ElseIf a = 2 Then
b = "c"
'...
End If
ただし、チェックする変数が1つまたは2つ以上ある場合、これは多くのコードスペースを占有する可能性があります(とにかくそれでも一般的にはより良い方法があります)。
代わりに、このSelect Case
ステートメントは、次のようにすべてを1つのブロックに入れることにより、チェックのサイズを削減するのに役立ちます。
Select Case a
Case 1:
b = "a"
Case 2:
b = "c"
'...
End Select
これによりコードがはるかに小さくなりますが、このような非常に単純な場合には、さらに効率的な方法があります。 Choose()
この関数は、渡された値に基づいてリストから値を選択します。
b = Choose(a,"a","c",...)
選択するオプション(a
この場合)は、最初の引数として渡される整数値です。後続のすべての引数は、選択する値です(ほとんどのVBAと同様に、1-indexed)。値は、設定されている変数と一致する限り任意のデータ型にすることができ(つまり、Set
キーワードなしではオブジェクトは機能しません)、式または関数にすることもできます。
b = Choose(a, 5 + 4, String(7,"?"))
追加のオプションは、Array
別のキャラクターを保存しながら同じ効果を得るために関数を使用することです:
b = Array(5 + 4, String(7,"?"))(a)
IIf()
他と組み合わせて使用することChoose()
です:A1=IIf(a=Choose(b,c,d,e),Choose(Choose(f,g,h,i),j,k,l),Choose(IIf(m=n,Choose(p,q,r,s),IIf(t=u,v,w)),x,y,z))
Excelが色を処理する方法のため(符号なし、6文字の16進整数)、負の符号付き整数を使用できますが、Excelでは色の値を割り当てるために右の6バイトのみを使用します
これは少しわかりにくいので、いくつかの例を以下に示します
次のように保存されている白を使用するとします。
rgbWhite
と同等です
&HFFFFFF ''#value: 16777215
これを下にゴルフするには、ネガティブを見つけるだけですで終了する16進数値FFFFFF
の形式でなければなりませんで、負の六角値と以降のFFFFXXXXXX
(ようX
からカウントダウン有効な16進です)FFFFFFFFFF
(-1
へ)FFFF000001
(-16777215
)
これを知って、式を一般化できます
Let Negative_Color_Value = -rgbWhite + Positive_Color_Value - 1
= -16777215 + Positive_Color_Value - 1
= -16777216 + Positive_Color_Value
これを使用すると、いくつかの便利な変換ができます
rgbWhite = &HFFFFFF = -1
rgbAqua = &HFFFF00 = -256
16747627 = &HFF8C6B = -29589
rgbWhite
= 2^24-1
ただし、-1を逃して大まかにそこに到達した場合は、さらに減らすことができます
&000080: 2^7, &000100: 2^8, &000200: 2^9, &000400: 2^10, &000800: 2^11, &001000: 2^12, &002000: 2^13, &004000: 2^14, &008000: 2^15, &010000: 2^16, &01FFFF: 2^17-1, &020000: 2^17, &03FFFF: 2^18-1, &040000: 2^18, &07FFFF: 2^19-1, &080000: 2^19, &0FFFFF: 2^20-1, &100000: 2^20, &1FFFFF: 2^21-1, &3FFFFF: 2^22-1, &400000: 2^22, &7FFFFF: 2^23-1
。nbは必ずしも完全ではありませんが、かなり徹底した仕事をしたと思います
"
イミディエイトウィンドウに印刷するときにターミナルを省略デバッグウィンドウで使用される以下の関数を考える
h="Hello":?h", World!"
ターミナル"
は-1バイトでドロップされ、文字列は閉じられず、プログラムはエラーなしで同じものを実行します。
h="Hello":?h", World!
これよりさらに驚くべきことは、これが完全に定義されたサブルーチン内で実行できることです。
Sub a
h="Hello":Debug.?h", World!
End Sub
上記のサブルーチンは期待どおりに実行され、自動フォーマットされます
Sub a()
h = "Hello": Debug.Print h; ", World!"
End Sub
LongLong
64ビットVBAの s累乗の一般的な形式、
A to the power of B
VBAのように表すことができます
A^B
ただし、Officeの32ビットインストールでのみ、Officeの 64ビットインストールでのみ、これはエラーなしで表すことができる最短の方法です。
A ^B
これは、64ビットバージョンのVBA ^
では、べき乗リテラルとLongLong
型宣言文字の両方として機能するためです。これは、次のようなかなり奇妙に見えるが有効な構文が発生する可能性があることを意味します。
a^=2^^63^-1^
a
aの最大値を保持する変数を割り当てますLonglong
一定のデータを保持するソリューションが必要なチャレンジでは、そのデータを単一の文字列として圧縮し、文字列全体を反復処理してデータを取得すると便利です。
VBAでは、任意のバイト値を文字に直接変換できます
Chr(byteVal)
そして、long
or integer
値は次のように2文字に変換されます。
Chr(longVal / 256) & Chr(longVal Mod 256)
したがって、byte
配列の場合、圧縮アルゴリズムは次のようになります
For Each Var In bytes
Select Case Var
Case Is = Asc(vbNullChar)
outstr$ = outstr$ & """+chr(0)+"""
Case Is = Asc(vbTab)
outstr$ = outstr$ & """+vbTab+"""
Case Is = Asc("""")
outstr$ = outstr$ & """"""
Case Is = Asc(vbLf)
outstr$ = outstr$ & """+vbLf+"""
Case Is = Asc(vbCr)
outstr$ = outstr$ & """+vbCr+"""
Case Else
outstr$ = outstr$ & Chr$(Var)
End Select
Next
Debug.Print "t="""; outstr$
そのことに注意してください Select Case
文字列にリテラルとして格納されない可能性のある文字のためにセクションが実装されることに注意してください。
結果の文字列から、次のようになります
t="5¼-™):ó™ˆ"+vbTab+"»‘v¶<®Xn³"+Chr(0)+"~ίšÐ‘š;$ÔÝ•óŽ¡¡EˆõW'«¡*{ú{Óx.OÒ/R)°@¯ˆ”'®ïQ*<¹çu¶àªp~ÅP>‹:<«a°;!¾y›/,”Ì#¥œ5*B)·7
次にAsc
、Mid
関数を使用してデータを抽出できます。たとえば、
i=Asc(Mid(t,n+1))
VBAでは、場合によっては、定数値を必要とする式でリストされていない定数または不適切な定数を使用できます。これらは多くの場合レガシー値であり、適切な値よりも長さが短くなっています。
たとえば、rng.HorizantalAlignment
プロパティに値を保持させる場合、以下の値を使用でき ます。
これは、たとえば、テキストの中央にセルを設定することを意味します
rng.HorizantalAlignment=-4108
に短縮することができます
rng.HorizantalAlignment=3
不適切な定数値3
を適切な値に置き換えます-4108
。rng.HorizantalAlignment
プロパティ値を取得すると、適切な値が返されることに注意してください。この場合、それはになります-4108
。
長さが混在する一定の単一次元数値セットの場合、 必要な場合は、[{...}]
表記法を使用して範囲を宣言し、そのSplit(String)
表記法などを使用するよりも、数値配列に強制する 方が効率的です。
この方法を使用すると、 すべてのために発生しなければならない 。
例えば、
x=Split("1 2 34 567 8910")
として書かれている可能性があります
x=[{1,2,34,567,8910}]
このメソッドは直接インデックス付けを許可しませんが、forループを介した直接の反復を許可します。つまり、
For Each s In[{1,3,5,7,9,2,4,6,8}]