VBA에서의 골프 팁


16

this , thisthis question 과 유사하게 ...

골프에 대한 일반적인 팁은 무엇입니까 VBA? 나는 일반적으로 다소 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다 VBA(예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.

다른 언어로 작업했지만 가장 VBA강하고이 VBA사이트에서 많은 골퍼를 사용 하는 것을 보지 못했습니다 .


정책에 따라 커뮤니티 위키로 변환되었습니다.
dmckee ---

그건 내 부분이 자동적이지 않아서 미안해!
Gaffi

문제 없습니다. 실제로, 그들은 사용자로부터 CW로부터 질문을 할 수있는 힘을 얻었습니다 (여전히 답을 할 수 있다고 생각합니다). 중재자의 관심을 끌기 위해 플래그를 지정할 수는 있지만 CodeGolf만큼의 활동은 거의 필요하지 않습니다.
dmckee --- 전 운영자 고양이

2
VBA는 구문 단축키가 거의없는 비교적 장황한 언어입니다. 최고 점수를 얻으려면 VBA가 적합하지 않을 수 있습니다. 기술을 연마하려는 경우 나중에 더 많은 힘을 얻으십시오.
Mr. Llama

2
@GigaWatt 내 기술을 연마합니다. 실제로 여러 가지 도전 과제를 해결 한 이후로 VBA 작업을위한 몇 가지 새로운 트릭을 이미 선택했습니다! VBA로 실제 코드 골프 과제 에서 이길 것으로 기대하지는 않지만 좋은 습관입니다. :-)
Gaffi

답변:


8

취약성 공격 ByRef잠수함을 호출 할 때 기본

경우 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"By Value"전달 (복사본) 와 반대 ). 전달 된 변수를 수정하면 호출 함수로 다시 변환됩니다.

기본적으로 는 모든 인수를로 사용 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

7

직접 실행 창에서 VBA 코드 작성 및 실행

직접 실행 창은 유효한 VBA 실행 문을 평가합니다. 코드 편집기에서와 같이 직접 실행 창에 명령문을 입력하기 만하면됩니다. VBA 코드를 빠르게 실행하며 다음과 같은 이유로 많은 추가 문자를 저장할 수 있습니다.

  1. 문의 시작 부분에 물음표 (?)를 넣으면 직접 실행 창에 코드 결과가 표시됩니다.

여기에 이미지 설명을 입력하십시오

  1. 코드에서 Sub 및 End Sub를 사용할 필요는 없습니다.

여기에 이미지 설명을 입력하십시오


다음은 직접 실행 창에있는 tag PPCG의 게시물에 응답하는 VBA 코드의 예입니다 . A가없는 Letter A

?Chr(88-23);

Joffan이 답변했습니다 .


크레딧 이미지 : Excel Campus


1
그래도 REPL 환경을 사용합니까? 즉, 그것은 단지 조각이 아닌 프로그램이나 기능입니다
coinheringaahing 케어 드

추가해야 할 또 다른 예는 변수를 인라인으로 만들 수도 있다는 것입니다. 예를 들어 a="value":?a먼저의 값을 설정 a한 다음 인쇄합니다.
Greedo

6

루핑 전 조건부 점검

루프와 함께 사용하면 일부 조건부 검사가 중복됩니다. 예를 들어 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

하단의 설명이 잘못되었습니다. B = 0이면 루프가 입력됩니다. pastebin.com/97MBB7hq
QHarr

5

변수 선언

대부분의 경우 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해당 변수 가 필요할 수 있습니다 .


잠깐만, 당신은 당신의 질문에 대한 자신의 대답을 받아 들였습니다. 멋지지 않아, 친구
Taylor Scott

1
@TaylorScott 그것은 위키 포스트입니다-요점은 없으며,이 경우에는 하나의 최선의 답변이 없습니다. :) 질문 목록에 깃발이 표시되지 않도록 ~ 5 년 전 답변을 수락합니다.
Gaffi

1
당신이 당신의 자신의 대답에 동의하면 @TaylorScott 또한, 당신은 (받아들이는) 15 또는 2 얻을하지 않습니다
coinheringaahing 케어 드

5

Evaluate()[]

앞에서 지적했듯이 대괄호 [A1]표기법을 사용하여 하드 코딩 된 범위 통화를 줄일 수 있습니다 . 그러나 그것보다 더 많은 용도가 있습니다.

MSDN documentation 에 따르면 이 Application.Evaluate()방법은 단일 인수를 취합니다.Name Microsoft Excel의 명명 규칙에 정의 된대로 .

마지막에 다루는 몇 가지 중요한 차이점이 있지만 NB [string]는 줄임말 Evaluate("string")( ""문자열 데이터 유형을 나타내는 음성 표시 참고 )입니다.

그렇다면 사용법의 의미는 무엇입니까?

기본적 [some cell formula here]으로 Excel 워크 시트에서 셀을 나타내며 셀에 거의 아무것도 넣지 않고 일반 셀로 할 수있는 것을 얻을 수 있습니다

무슨 일이야

예제와 함께 요약하면

  • A1 스타일 참조. 모든 참조는 절대 참조로 간주됩니다.
    • [B7] 해당 셀에 대한 참조를 반환합니다
    • 참조는 절대입니다으로 ?[B7].Address반환"B$7$"
  • 범위 참조, 범위, 교차 및 공용체 연산자 (각각 콜론, 공백 및 쉼표)를 사용할 수 있습니다.
    • [A1:B5]A1:B5(범위)에 대한 범위 참조를 반환합니다.
    • [A1:B5 A3:D7]A3:B5(교차)에 대한 범위 참조를 반환합니다.
    • [A1:B5,C1:D5]A1:D5(기술적으로 A1:B5,C1:D5) (Union)에 대한 범위 참조를 반환합니다.
  • 정의 된 이름
    • [myRange]A1 : G5 와 같은 사용자 정의
    • 테이블 이름과 같은 자동 [Table1](코드 골프에는 덜 유용 할 수 있음)
    • [Formulas]> [Name Manager]메뉴 에서 찾을 수있는 다른 것
  • 방식
    • 매우 유용합니다 . 셀에 갈 수있는 공식에 갈 수 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)
  • 차트 개체 (MSDN 기사 참조)

NB 나는이 정보에 대해 SO에 대해 질문을 했으므로 더 나은 설명을 위해 거기 를 살펴보십시오.

무엇이 나오는지

들어오는 것과 비슷하게 나오는 것은 워크 시트 셀이 반환 할 수있는 모든 것을 포함합니다. 다음은 표준 Excel 데이터 형식 및 해당 VBA 형식입니다.

  • 논리 ( Boolean)
  • 텍스트 ( String)
  • 숫자 (Double )
  • 오류 ( Variant/Error) (이것은 오류 가 아닌 오류입니다. 즉, 코드 실행을 중단하지 않고 ?[1/0]정상적으로 실행됩니다)

그러나 셀이 할 수없는 몇 가지 반환 할 수있는 것들이 있습니다.

  • 범위 기준 ( Range) (위 섹션 참조)
  • 배열 ( Variant())

배열

표시된 것처럼 []표준 Excel 데이터 형식 중 하나를 반환하는 배열 수식을 평가하는 데 사용할 수 있습니다. 예를 들어 [CONCAT(IF(LEN(A1:B7)>2,A1:B7&" ",""))]어떤 돌아갑니다 Text. 그러나 형식의 Evaluate배열을 반환 할 수도 있습니다 Variant. 이것들은

하드 코드 :

[{1,2;3,4}]-2D 배열을 출력합니다 ,. 열 구분 기호이며 ;행을 구분합니다. 1D 배열을 출력 할 수 있습니다

배열 공식 :

[ROW(A1:A5)]-2D 배열을 출력합니다 {1,2,3,4,5}. 즉 (2,1)은 두 번째 항목입니다 (그러나 일부 함수는 1D 배열을 출력합니다)

  • 어떤 이유로 든 일부 함수는 기본적으로 배열을 반환하지 않습니다

[LEN(A1:A5)] 범위의 첫 번째 셀에있는 텍스트의 길이 만 출력합니다

  • 그러나 이것들은 강제로 배열을 제공 할 수 있습니다

Split([CONCAT(" "&LEN(A1:A5))]) 첫 번째 항목이 비어있는 1D 배열 0 ~ 5를 제공합니다.

[INDEX(LEN(A1:A5),)]또 다른 해결 방법입니다. 기본적으로 RAND()워크 시트 수식을 휘발성으로 만들기 위해 의미없는 것을 추가하는 것과 마찬가지로 원하는 배열 반환 동작을 얻으려면 배열 처리 함수를 사용해야합니다 .

  • 나는 이것에 대한 더 나은 정보를 얻으려고 SO대한 질문을했다. 당신이 그들을 찾으면 더 나은 옵션으로 편집 / 코멘트하십시오

Evaluate() vs []

몇 가지 차이점 사이에 있습니다 Evaluate()[]인식하려면

  1. 문자열 대 하드 코딩
    • 아마도 가장 중요한 차이점 인 Evaluate는 []에 하드 코딩 된 입력이 필요한 문자열 입력을 사용합니다
    • 이 의미 예를 들어 변수와 문자열을 구축 할 수 있습니다 코드 Evaluate("SUM(B1,1,"&v &",2)")요약 것이다 [B1], 1, 2및 변수를v
  2. 배열

    배열을 반환 할 때 Evaluate 만 배열 인덱스와 함께 사용할 수 있으므로

    v=Evaluate("ROW(A1:A5)")(1,1) ''#29 bytes

    에 해당

    i=[ROW(A1:A5)]:v=i(1,1) ''#23 bytes

매머드 게시물에 대해 죄송합니다. 누군가가 영역을 더 간결하게 만들 수 있다고 생각하면 추가 할 팁이 있으면 자유롭게 느끼십시오. 또한이 중 일부를 연구했지만 VBA에서 실험을 통해 상당한 부분을 발견했기 때문에 누락 된 부분이 있다고 느끼는 실수를 발견하면 주저하지 말고 의견을 보내십시오!
Greedo

1
실제로 어레이의 마지막 섹션은 약간 벗어났습니다. 즉석 창에서 사용할 수 있습니다i=[ROW(A1:A5)]:v=i(2,1):?v
Taylor Scott

@TaylorScott 그래서 당신은 할 수 있습니다, 당신은 아직 정의되지 않은 변수에 값을 설정 / 보유 할 수 있다는 것을 전혀 알지 못했지만, 직접 실행 창 1-라이너를 계속 잡고 있기 때문이라고 생각합니다. 이에 따라 업데이트
Greedo

이 기능이 일치합니까? 시도했지만 항상 오류를 반환합니다. 그래도 범위 대신 배열을 전달하고있었습니다.
seadoggie01

5

결합 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 i=0To[A1]
    For j=0To[B1]
        For k=0To[C1]
            Debug.?i;j;k
Next k,j,i

4

If진술 감소

조건부 If ... Then ... Else검사를 사용하여 변수를 할당 할 때 End If전체 검사를 한 줄로 수행 하여 코드를 제거함으로써 사용되는 코드의 양을 줄일 수 있습니다 .

예를 들면 다음과 같습니다 ( 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)

3

Range("A1")전화를 줄이고 좋아

Range("A1").Value(17 바이트)와 더 간단한 Range("A1")(11 바이트)을 [A1](4 바이트) 로 줄일 수 있습니다


2
또는 일반적으로 VBA []에서 대체 Evaluate()를 사용하는 것은 단순히 범위 통화보다 훨씬 다양합니다. 예 : 당신은 대체하는 데 사용할 수 있습니다 WorksheetFunction.FuncName(args)와 함께 단지 [FuncName(args)], 같은 ?[SUMPRODUCT({1,3,5},{2,7,-1})]또는 매우 유용 [MIN(1,2,3)]/[MAX(1,2,3)]
Greedo

Greedo, 그것은 당신이 알지 못했던 매우 중요한 기능이며, 이것을 자체 답변으로 추가해야합니다.
Taylor Scott

1
물론, 곧 뭔가를 쓸 것입니다. 예 Evaluate("str")또는 속기 [str]는 VBA에서 매우 강력하며 최근에 알게 된 사실이며 골프에도 도움이 될 것입니다!
Greedo

매우 유용하고, 충분한 답변을 가지고 있기 때문에 바이트 수를 줄일 수 있는지 알아보기 위해 대답을 다시 살펴볼 것입니다.
Taylor Scott

3

공백 제거

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가 특정 명령이 나타날 것으로 예상되는 패턴을 따르는 것 같습니다. 여기까지 내가 찾은 것들이 있습니다 :

  • 수학 연산 전후 : +-=/*^
  • ToStepA의 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것이 허용되지만 &변수 eg 직후 에 형식 선언 을하는 것은 예를 들어 Debug.?a&"z"제공합니다 Debug.Print a&; "z". ;추가 된 문자는 코드를 실행하는 데 필수적입니다. 여전히 허용됩니까?
Greedo

2
@Greedo 메타 답변이 설명 하는 방식을 봅니다 . 편집기에 복사하여 붙여 넣을 수 있고 코드가 실행되면 괜찮습니다. IE, 코드를 붙여 넣을 때 VBA가 자동으로 문자를 다시 추가하면 괜찮습니다.
엔지니어 토스트

1
당신이 실제로 예를 떨어져 또 하나의 바이트를 삭제할 수 있습니다 @EngineerToast : If i=1 Then 될 수 있습니다 If i=1Then 일반적 리터럴을 다음 예약 된 단어로, 숫자일지도 때문에 ), ?, %, ... 등으로 구분 할 필요가 없습니다 공간
Taylor Scott

1
@EngineerToast, 당신은 또한 )(또는 다른 숫자가 아닌 다른 리터럴)과&
Taylor Scott

3

픽셀 아트를위한 준비

픽셀 아트는 이미 캔버스를 만들 필요가 없기 때문에 Excel의 가장 강력한 영역 중 하나입니다. 작은 조정 만하면됩니다.

1) 세포를 정사각형으로 만듭니다.

Cells.RowHeight=48

또는 대안으로 1 바이트 이상이지만 작업하기가 훨씬 쉽습니다.

Cells.ColumnWidth=2

2) 필요한 범위를 채색

전화를 통해 모든 Range개체에 색상을 지정할 수 있습니다

`MyRangeObj`.Interior.Color=`ColorValue`

참고 : 이것은이 위키에 언급 된 다른 트릭과 결합 될 수 있으며 , 또는 호출 사용에 대한 []표기법 (예 :)을 사용하여 범위를 참조하는 등의 방법을 [A1:R5,D6]사용할 수 있습니다 . 또한,이 위키에서 언급 한 바와 같이, 이것은 음의 색상 값과 결합하여 색상 참조의 크기를 줄입니다. Cells(r,c)Range(cellAddress)

빠른 참조

범위 기준

A1은 다음 방법 중 하나로 참조 될 수 있습니다.

Range("A1")
Cells(1,1)
[A1]

Range 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

3

내장 함수 단순화

특정 기능을 자주 사용하는 경우 사용자 정의 기능에 다시 할당하십시오.

다음 코드 ( 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. 두 번째 코드 블록은 실제와 처음보다 더 큰 것이 어떤 번호를 적은 Format()전화.


2
마지막으로, 당신은 그 의미 할당 호출이 필요하지 않습니다 a = f(w)줄일 수있다f w
테일러 스콧

3

STDIN과 STDOUT

입력 변수를 통해 Sub루틴 및 Functions에 입력

Public Sub A(ByRef B as String)

로 축소 될 수 있습니다

Sub a(b$) 

PublicByRef호출 VBA 따라서 암시의 기본이며, (거의) 항상 삭제 될 수 있습니다.

형식 리터럴 $b형식이 String됩니다.

다른 타입 리터럴

  • ! 단일
  • @ 통화
  • # 더블
  • % 정수
  • $
  • &
  • ^ LongLong (64 비트 만 해당)

또한 일반적으로 입력 변수를 기본 유형으로 Variant남겨두고 유형 기반 오류를 처리하지 않은 채로 둘 수 있습니다. 예 : Sub E(F)하는 F형식이 될 것으로 예상된다 Boolean[](같은 루틴에 전달 될 것이다 E Array(True, False, False))

다음을 Sub통해 루틴 및 즉시 창 기능에 입력Cells

VBA에는 완전한 기능을 갖춘 콘솔이 없으므로 공식 STDIN 이 없으므로 입력을 통과 하면서 약간의 플레이가 가능합니다.

엑셀에서, 일반적으로 셀 또는 셀 범위로부터 입력을받는 것이 받아 들여지며, 이는 다음과 같이 수행 될 수있다

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루틴 및 Functions 에서 출력

VBE 즉시 실행 창 (일명 VBE 디버그 창)으로 출력하는 것은 텍스트 기반 챌린지에 대한 VBA의 일반적인 출력 방법이지만 Debug.Print "Text"호출이 실질적으로 진행될 수 있음 을 기억해야합니다 .

Debug.Print "Text"

기능적으로 동일하다

Debug.?"Text"

?자동 형식으로 Print.

Sub다른 방법을 통해 루틴 및 VBE 즉시 실행 창 기능 에서 출력

드문 상황이 바로 때 때, 당신은 글꼴 크기 조정, 글꼴 선택으로 VBA 사용할 수있는 더 사소한 입력의 일부에서 입력을하고, 확대 할 수있다. (예 : 단어 글꼴 크기 선택기 에뮬레이션 )


2

서식에 대한 빠른 참고

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 답변 보다 형식이 더 이상 합니다.
Greedo

1
@Greedo lang-vba는 강조 표시를 제공하지만 실제로 기본 강조 표시 만 제공 하기 때문 입니다. VBA는 실제로 Prettify.js에서 구현되지 않았으므로 VB 강조 표시를 사용해야합니다.
Taylor Scott

2

여러 If .. Then검사

다른 언어와 마찬가지로, 여러 If검사는 보통의 사용을 허용 한 라인으로 결합 할 수 있습니다 And/ Or(예 : &&/ ||VBA에서 모두 대체, 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

1
"If-if"에서 "End-if"부분은 선택 사항이므로 한 줄로 코드를 작성해야합니다.
Stupid_Intern

@newguy 맞습니다. 이 다른 답변도보십시오 : codegolf.stackexchange.com/a/5788/3862
Gaffi

위의 진술은 다음과 같이 요약 될 수 있습니다.d=iif(a=b or c=b,0,d)
Taylor Scott

2

엔딩 For루프

For루프를 사용할 때 Next행에는 변수 이름이 필요하지 않습니다 (일반 코딩에 사용하는 것이 더 나을 수도 있음).

따라서,

For Variable = 1 to 100
    'Do stuff
Next Variable

단축 할 수 있습니다 :

For Variable = 1 to 100
    'Do stuff
Next

(저축은 변수 이름에 따라 다르지만 골프를 타는 경우 1 자 + 1 자 정도일 것입니다.)


1
2 자, 공간을 세는 것을 잊지 마십시오!
11684

정상적인 코드에서도 변수를 거의 식별하지 못합니다!
dnep

2

문자열을 문자형 배열로 분할

때로는 문자열을 개별 문자로 분리하는 것이 유용 할 수 있지만 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

대신, 작업을 완료하기 위해 한 줄의 상대적으로 최소한의 함수 체인을 사용할 수 있습니다.

a = Split(StrConv(s, 64), Chr(0))

이것은 문자열 sVariantarray에 할당합니다 a. 그러나 배열의 마지막 항목은 빈 문자열 ( "")이므로 적절하게 처리해야합니다.

작동 방식은 다음과 같습니다.이 StrConv함수는 a String를 다른 형식으로 변환합니다 . 이 경우 64 = vbUnicode이므로 유니 코드 형식으로 변환됩니다. 간단한 ASCII 문자열을 처리 할 때 결과는 빈 문자열이 아닌 null 문자입니다."" 각 문자 뒤에 삽입 된 아님)입니다.

다음 SplitStringnull 문자 Chr(0)를 구분 기호로 사용하여 결과 를 배열로 변환합니다 .

Chr(0)빈 문자열 ""과 동일하지 않다는 점에 유의해야 하며 Spliton ""을 사용 하면 예상 한 배열이 반환되지 않습니다. vbNullString골프 도 마찬가지 인데, 왜 그런 장황한 상수를 처음에 사용하겠습니까?).


결과 배열의 끝에 추가 빈 문자열이 있음을 언급해야합니다.
Howard

@Howard 그렇습니다. 내가 이것을 타이핑하는 동안 그것은 내 머리 속에 있었고, 내 마음을 미끄러 뜨렸을 것입니다.
Gaffi

2

사용 With(때때로! 참조 각주)

사용하여 With 반복적 일부 개체를 사용하여 크게 if 문은 코드의 크기를 줄일 수 있습니다.

즉이 ( 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

2

무한 루프

교체를 고려해보다

Do While a<b
'...
Loop

또는

Do Until a=b
'...
Loop

구식이지만 적은 바이트 수

While a<b
'...
Wend

a 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모든 코드 실행 을 중지하고 전역 변수를 지우므로 현명하게 사용하십시오.


마지막 섹션 ( ForEnd)을 다시 작성하여 사건 100이 충족되지 않고 불필요한 바이트를 추가 할 수 있음을 반영해야합니다.
Taylor Scott

또한 이것은 읽기 쉬운 반면, 공백을 제거하면 이러한 방법의 가능한 이점을 더 잘 보여줄 수 있습니다 (코드 골프를 위해 VBA에서 자동 서식을 남용하는 것이 좋습니다)
Taylor Scott

2

사용 Spc(n)을 통해 Space(n), [Rept(" ",n)]또는String(n," ")

길이가 여러 개인 공백을 삽입하려는 n경우

Spc(n)              ''  6  bytes

위에

B1=n:[Rept(" ",B1)] ''  19 bytes
String(n," ")       ''  13 bytes
Space(n)            ''  8  bytes

참고 : 이유는 확실하지 않지만 Spc(n)변수 의 출력을 변수에 할당 할 수 없으며 오히려 직접 인쇄 해야하는 것처럼 보입니다. 따라서 어떤 경우 Space(n)에는 여전히 가장 좋은 방법입니다.


2

감소 Debug.PrintPrint통화

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

2

도우미 Sub를 사용 하여Print

코드에서 6 개 이상의 Debug.? 문을 사용해야하는 경우 모든 디버그를 바꾸어 바이트를 줄일 수 있습니다. 아래와 같이 Sub에 대한 호출이있는 회선. 빈 줄을 인쇄하려면 p ""매개 변수가 필요하므로 전화해야 합니다.

Sub p(m)
Debug.?m
End Sub

1
새 줄을 인쇄하려면 필요한 p""경우 또는 종료 할 수없는 경우 p". 그러나 이것이 적용될 수있는 대부분의 경우 문자열 변수를 사용하고 끝에 문자열 변수 만 인쇄하는 것이 더 합리적입니다.
Taylor Scott

1

또는 Array() Choose()대신 사용SelectIf...Then

다른 변수의 값을 기반으로 변수를 할당 할 때 다음과 같이 If...Then검사로 단계를 작성하는 것이 좋습니다 .

If a = 1 Then
b = "a"
ElseIf a = 2 Then
b = "c"
'...
End If

그러나 확인할 하나 또는 두 개 이상의 변수가있는 경우 많은 코드 공간을 차지할 수 있습니다 (아직 어쨌든 일반적으로 더 나은 방법이 있습니다).

대신,이 Select Case명령문은 다음과 같이 모든 것을 하나의 블록으로 묶어 검사 크기를 줄이는 데 도움이됩니다.

Select Case a
Case 1:
b = "a"
Case 2:
b = "c"
'...
End Select

이것은 훨씬 작은 코드로 이어질 수 있지만 이와 같은 매우 간단한 경우에는 훨씬 더 효율적인 방법 Choose()이 있습니다 . 이 함수는 전달 된 값을 기반으로 목록에서 값을 선택합니다.

b = Choose(a,"a","c",...)

선택하는 옵션 ( a이 경우)은 첫 번째 인수로 전달 된 정수 값입니다. 이후의 모든 인수는 선택할 수있는 값입니다 (대부분의 VBA와 마찬가지로 1- 색인). 값은 설정중인 변수와 일치하는 한 (즉, 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))
Gaffi

1

비트 시프 팅 된 RGB 값

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을 놓치면 더 줄어들 수 있습니다
Greedo

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 반드시 완료 할 필요는 없지만 상당히 철저한 작업을 수행 한 것 같습니다
Greedo

1

직접 실행 "창으로 인쇄시 터미널 생략

디버그 창에서 사용될 아래 기능이 주어지면

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

1

조건부에서 Truthy 및 Falsey 변수 사용

직접에 숫자 유형을 사용하여 - 때로는 암시 적 형식 변환이라고 If, [IF(...)]또는IIf(...) 문, 그 수 할 수있는 절대적으로 저장 일부 바이트 truthy 및 falsey 특성을 사용하여.

VBA에서 0이 아닌 모든 숫자 유형 변수는 진실한 것으로 간주되므로 (0 0은 유일한 값은 거짓입니다)

If B <> 0 Then 
    Let C = B
Else 
    Let C = D
End If 

응축 될 수 있습니다

If B Then C=B Else C=D

그리고 더

C=IIf(B,B,D)

1

이름 별 주소지

WorkSheet호출 하여 객체 주소 지정 대신

Application.ActiveSheet
''  Or 
ActiveSheet   

하나는 사용할 수 있습니다

Sheets(n)  ''  Where `n` is an integer
''  Or 
[Sheet1]

또는보다 바람직하게는 물체에 직접 접근하여 사용할 수있다

Sheet1

1

LongLong64 비트 VBA의 지수 및 s

지수의 일반적인 형태

A to the power of B

VBA 에서처럼

A^B 

그러나 32 비트 Office 설치에서만 , 64 비트 Office 설치에서는 오류없이 나타낼 수있는 가장 짧은 방법은 다음과 같습니다.

A ^B

이는 64 비트 버전의 VBA ^에서 지수 리터럴과 LongLong형식 선언 문자 로 사용되기 때문입니다 . 이것은 다소 이상하게 보이지만 유효한 구문이 발생할 수 있음을 의미합니다.

a^=2^^63^-1^

변수 a의 최대 값을 보유하도록 변수 를 할당합니다 .Longlong


1

바이트 배열을 문자열로 압축

솔루션에 일정한 데이터를 유지해야하는 칼랑의 경우 해당 데이터를 단일 문자열로 압축 한 다음 문자열을 반복하여 데이터를 가져 오는 것이 유용 할 수 있습니다.

VBA에서 모든 바이트 값은 다음과 같은 문자로 직접 변환 될 수 있습니다.

Chr(byteVal)

그리고 a long또는 integervalue는 다음 두 문자로 변환 될 수 있습니다.

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    

그런 다음 AscMid기능을 사용하여 데이터를 추출 할 수 있습니다.

i=Asc(Mid(t,n+1))

1

부적절한 상수 사용

경우에 따라 VBA를 사용하면 상수 값이 필요한 표현식에 나열되지 않거나 부적절한 상수를 사용할 수 있습니다. 이들은 종종 레거시 값이며 적절한 값보다 길이가 짧습니다.

예를 들어 아래 값은 rng.HorizantalAlignment속성에 의해 값을 유지하게 할 때 사용될 수 있습니다 .

부적절한적절한일반 상수할리 겐  일정한11xl 일반xlHAlignGeneral24131왼쪽xlHAlignLeft4108xlCenterxlHAlignCenter44152xl 오른쪽xlHAlignRight55xlFillxlHAlignFill64130xlJustifyxlHAlignJustify77xlCenterAcrossSelectionxlHAlignCenterAcrossSelection84117xl 배포xlHAlign 분산

예를 들어 셀의 텍스트가 중앙에 위치하도록 설정하는 것은

rng.HorizantalAlignment=-4108

로 단축 될 수 있습니다

rng.HorizantalAlignment=3

3적절한 값으로 부적절한 상수 값 을 대체하여 -4108. rng.HorizantalAlignment속성 값 을 가져 오면 적절한 값이 반환됩니다. 이 경우에는입니다 -4108.


1

Excel에서 범위를 강제 변환하여 숫자 형 배열 만들기

에스[{...}]Split(String) 표기법 입니다.

Δ바이트 수=5 바이트에스

예를 들어

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}]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.