เคล็ดลับสำหรับการเล่นกอล์ฟใน VBA


16

คล้ายกับนี้ , นี้และนี้คำถาม ...

สิ่งใดที่คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟในVBA? ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งค่อนข้างเฉพาะเจาะจงได้VBA (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ

ในขณะที่ฉันทำงานกับภาษาอื่นฉันแข็งแกร่งที่สุดVBAและฉันไม่เห็นนักกอล์ฟจำนวนมากที่ใช้VBAเว็บไซต์นี้


แปลงเป็น Community Wiki ตามนโยบาย
dmckee --- ผู้ดูแลอดีตลูกแมว

ขออภัยที่ไม่ได้เป็นไปโดยอัตโนมัติในส่วนของฉัน!
Gaffi

ไม่มีปัญหา. ที่จริงแล้วพวกเขาใช้พลังเพื่อตั้งคำถาม CW ห่างจากผู้ใช้ (คุณยังสามารถตอบได้ฉันคิดว่า) คุณสามารถตั้งค่าสถานะเพื่อให้ผู้ดูแลสนใจ แต่กิจกรรมเล็ก ๆ น้อย ๆ ตามที่ CodeGolf ได้รับนั้นไม่จำเป็น
dmckee --- ผู้ดูแลอดีตลูกแมว

2
VBA เป็นภาษา verbose ค่อนข้างมีทางลัดไวยากรณ์น้อย หากคุณทำคะแนนได้ดีที่สุด VBA อาจไม่ใช่ทางเลือกที่ดี หากคุณกำลังมองหาการฝึกฝนทักษะของคุณ
Mr. Llama

2
@GigaWatt เพิ่มพูนทักษะของฉัน ที่จริงแล้วตั้งแต่เล่นกับความท้าทายที่แตกต่างกันฉันได้รับเคล็ดลับใหม่สำหรับการทำงานกับ VBA! ผมไม่ได้คาดหวังว่าจะชนะจริง รหัสกอล์ฟท้าทายด้วย VBA แต่มันเป็นเรื่องการปฏิบัติที่ดี :-)
Gaffi

คำตอบ:


8

ใช้ประโยชน์จากByRefค่าเริ่มต้นเมื่อเรียกหมวดย่อย

บางครั้งเป็นไปได้ที่จะใช้การSubโทรแทน a 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โทรแทน สิ่งนี้หมายความว่าอะไรคืออาร์กิวเมนต์ที่ผ่านเป็นตัวแปรเดียวกันในฟังก์ชั่นการโทร (ตรงข้ามกับ aByValส่งผ่าน "โดยค่า" ซึ่งเป็นสำเนา) การแก้ไขตัวแปรส่งผ่านใด ๆ จะแปลกลับไปยังฟังก์ชันการโทร

โดยค่าเริ่มต้นรับข้อโต้แย้งทั้งหมดในฐานะ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 ในหน้าต่าง Immediate

หน้าต่าง Immediate ประเมินข้อความสั่ง VBA ที่ถูกต้องใด ๆ เพียงป้อนคำสั่งในหน้าต่างทันทีตามที่คุณต้องการในเครื่องมือแก้ไขรหัส มันรันรหัส VBA อย่างรวดเร็วและสามารถบันทึกอักขระเพิ่มเติมได้เนื่องจาก:

  1. การใส่เครื่องหมายคำถาม (?) ที่จุดเริ่มต้นของข้อความแจ้งให้หน้าต่างทันทีเพื่อแสดงผลลัพธ์ของรหัสของคุณ

enter image description here

  1. คุณไม่จำเป็นต้องใช้ Sub และ End Sub ในรหัสของคุณ

enter image description here


นี่คือตัวอย่างของรหัส VBA ในหน้าต่างค้นหาคำตอบของ PPCG พร้อมกับแท็ก : The Letter A without A

?Chr(88-23);

ตอบโดยJoffan


ภาพเครดิต: Excel Campus


1
ที่ใช้สภาพแวดล้อม REPL แม้ว่า ซึ่งหมายความว่ามันเป็นเพียงตัวอย่างเท่านั้นไม่ใช่โปรแกรมหรือฟังก์ชั่น
caird 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 มันเป็น wiki post - no points และในกรณีนี้ไม่มีคำตอบเดียวที่ดีที่สุด :) ฉันยอมรับคำตอบ ~ 5 ปีก่อนเพื่อหลีกเลี่ยงการตั้งค่าสถานะในรายการคำถามของฉัน
Gaffi

1
@TaylorScott เช่นกันหากคุณยอมรับคำตอบของคุณเองคุณจะไม่ได้รับ +15 หรือ +2 (สำหรับการตอบรับ)
caird coinheringaahing

5

Evaluate() และ []

ดังที่ได้กล่าวไว้ก่อนหน้านี้การโทรแบบช่วงที่กำหนดค่าตายตัวสามารถลดลงได้โดยใช้[A1]สัญกรณ์วงเล็บเหลี่ยม อย่างไรก็ตามมันมีประโยชน์หลายอย่างมากกว่าแค่นั้น

ตามที่ เอกสาร MSDNที่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 (Intersect)
    • [A1:B5,C1:D5]ส่งคืนการอ้างอิงช่วงถึงA1:D5(ทางเทคนิคA1:B5,C1:D5) (ยูเนี่ยน)
  • ชื่อที่กำหนด
    • ผู้ใช้กำหนดเช่น[myRange]อ้างอิงถึง A1: G5
    • อัตโนมัติเช่นชื่อตาราง[Table1](อาจมีประโยชน์น้อยกว่า codegolf)
    • อะไรก็ได้ที่คุณสามารถหาได้ในเมนู[Formulas]>[Name Manager]
  • สูตร
    • มีประโยชน์มาก ; สูตรใดก็ได้ที่สามารถเข้าไปในเซลล์สามารถเข้าไปEvaluate()หรือ[]
    • [SUM(1,A1:B5,myRange)]ส่งกลับผลรวมเลขคณิตของค่าในช่วงmyRange ที่นี่หมายถึงชื่อเวิร์กบุคไม่ใช่ตัวแปร VBA
    • [IF(A1=1,"true","false")](1 ไบต์สั้นกว่า vba เทียบเท่าIif([A1]=1,"true","false"))
    • Array formulas [CONCAT(IF(LEN(A1:B7)>2,A1:B7&" ",""))]- รวมสตริงทั้งหมดในช่วงที่ความยาวมากกว่า 2 มีช่องว่าง
  • การอ้างอิงภายนอก
    • คุณสามารถใช้!โอเปอเรเตอร์เพื่ออ้างอิงเซลล์หรือชื่อที่กำหนดในสมุดงานอื่น
    • [[BOOK1]Sheet1!A1]ส่งคืนการอ้างอิงช่วงถึง A1 ใน BOOK1 หรือ['[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ประเภท สิ่งเหล่านี้สามารถ

hardcoded:

[{1,2;3,4}]- เอาต์พุตอาร์เรย์ 2 มิติ: ,เป็นตัวคั่นคอลัมน์;แยกแถว สามารถส่งออกอาร์เรย์ 1D

สูตรอาร์เรย์:

[ROW(A1:A5)]- ส่งออกอาร์เรย์2 มิติ{1,2,3,4,5}คือ (2,1) เป็นรายการที่สอง

  • ไม่ว่าด้วยเหตุผลใดก็ตามฟังก์ชั่นบางอย่างจะไม่ส่งคืนอาร์เรย์ตามค่าเริ่มต้น

[LEN(A1:A5)] เอาต์พุตความยาวของข้อความในเซลล์ที่ 1 ของช่วงเท่านั้น

  • อย่างไรก็ตามสิ่งเหล่านี้สามารถถูกบังคับให้มอบอาร์เรย์

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. อาร์เรย์

    เมื่อส่งคืน Array จะมีเพียง Evaluate เท่านั้นที่สามารถใช้กับดัชนี Array ได้

    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-liners ได้อัปเดตตามลำดับ
Greedo

สิ่งนี้ใช้ได้กับการจับคู่หรือไม่ ฉันพยายาม แต่มันก็มักจะกลับข้อผิดพลาด แม้ว่าฉันจะผ่านอาร์เรย์แทนที่จะเป็นช่วง
seadoggie01

5

รวมNextงบ

Next:Next:Next

อาจจะข้นลงไป

Next k,j,i

ที่ iterators สำหรับ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")และกด Like

Range("A1").Value(17 ไบต์) และเรียบง่ายRange("A1")(11 ไบต์) อาจถูกลดขนาดลงเป็น[A1](4 ไบต์)


2
หรือโดยทั่วไปแล้วการใช้[]เพื่อแทนที่Evaluate()VBA นั้นมีความหลากหลายมากกว่าการใช้โทรศัพท์เพียงอย่างเดียว เช่นคุณสามารถใช้มันเพื่อแทนที่WorksheetFunction.FuncName(args)ด้วย just [FuncName(args)]เช่น?[SUMPRODUCT({1,3,5},{2,7,-1})]หรือ[MIN(1,2,3)]/[MAX(1,2,3)]
Greedo

Greedo นั้นเป็นฟังก์ชั่นที่สำคัญอย่างไม่น่าเชื่อที่ฉันไม่ทราบว่าคุณควรเพิ่มเข้าไปในคำตอบของมัน
เทย์เลอร์สกอตต์

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 คาดว่าจะมีคำสั่งบางอย่างปรากฏขึ้นเพราะหากไม่มีรหัสก็ไม่ถูกต้อง นี่คือบางส่วนที่ฉันพบ:

  • ก่อนและหลังการดำเนินการทางคณิตศาสตร์ใด ๆ : +-=/*^ฯลฯ
  • ก่อน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)

อะไรคือกฎของการเพิ่มอักขระที่ไม่ใช่ช่องว่างผ่านการจัดรูปแบบอัตโนมัติ สิ่งที่ต้องการ?เทียบกับPrintที่ผมเห็นเป็นที่ยอมรับ แต่วางที่ประกาศประเภทเช่น&ทันทีหลังจากที่เช่นตัวแปรให้Debug.?a&"z" ตัวละครเพิ่มเป็นสิ่งจำเป็นสำหรับรหัสการทำงาน - จะยังคงได้รับอนุญาต? Debug.Print a&; "z";
Greedo

2
@ เกรโด้ฉันเห็นวิธีที่คำตอบของเมตาอธิบายไว้: ถ้าคุณสามารถคัดลอก / วางลงในเครื่องมือแก้ไขและรหัสจะทำงานก็ใช้ได้ IE, ถ้า VBA เพิ่มตัวละครกลับโดยอัตโนมัติเมื่อคุณวางรหัสมันก็โอเค
Engineer Toast

1
@EngineerToast คุณจริงสามารถวางหนึ่งไบต์มากขึ้นออกจากตัวอย่างของคุณ: If i=1 Then อาจจะกลายเป็นIf i=1Then เพราะเป็นกฎทั่วไปคำสงวนที่ตามตัวอักษรว่าจะเป็นตัวเลข), ?, %.. ฯลฯ ไม่จำเป็นที่จะต้องแยกจากกันโดย space
Taylor Scott

1
@EngineerToast คุณยังสามารถวางไบต์จากสัญลักษณ์แสดงหัวข้อย่อยที่สามของคุณในขณะที่คุณสามารถวางช่องว่างระหว่าง)(หรือตัวอักษรอื่น ๆ ที่ไม่ใช่ตัวเลข) และ&
Taylor Scott

3

เตรียมพร้อมสำหรับ Pixel Art

Pixel Art เป็นหนึ่งในพื้นที่ที่แข็งแกร่งที่สุดของ Excel เนื่องจากไม่จำเป็นต้องสร้าง Canvas เนื่องจากมีอยู่แล้วสำหรับคุณ - สิ่งที่คุณต้องทำคือปรับแต่งเล็กน้อย

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
Taylor Scott

3

STDIN และ STDOUT

การป้อนข้อมูลไปยังรูทีนSubและFunctions ผ่านตัวแปรอินพุต

Public Sub A(ByRef B as String)

อาจจะลดลงไป

Sub a(b$) 

กระบวนการPublicและการByRefเรียกใช้เป็นค่าเริ่มต้นสำหรับ VBA และโดยนัยดังนั้นและอาจ (เกือบ) หลุดเสมอ

ประเภทตัวอักษร$กองกำลังที่จะเป็นชนิดที่bString

ตัวอักษรประเภทอื่น ๆ

  • ! เดียว
  • @ เงินตรา
  • # สอง
  • % จำนวนเต็ม
  • $ เชือก
  • & ยาว
  • ^ 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 (ดูผ่าน explorer โครงการ -> [โครงการ VBA ของคุณ] - (คลิกขวา) -> คุณสมบัติ VBAProject -> อาร์กิวเมนต์การรวบรวมแบบมีเงื่อนไข)

สิ่งนี้มีประโยชน์มากสำหรับการท้าทายรหัสข้อผิดพลาด

ได้รับการโต้แย้งเงื่อนไขการรวบรวมn=[some_value] nนี้จะช่วยให้การดำเนินรหัสที่จะผลิตรหัสข้อผิดพลาดตามออกของค่าของ หมายเหตุการเรียกนี้จะเพิ่ม 2 ไบต์ไปยังรหัสของคุณสำหรับn=ในส่วนอาร์กิวเมนต์การคอมไพล์ตามเงื่อนไขของ VBAProject Properties Pane

รหัสตัวอย่าง

...
#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 ทันที (ดูด้านล่าง)

เอาท์พุทจากรูทีนSubและFunctions ผ่านหน้าต่าง VBE ทันที

การแสดงผลไปยังหน้าต่าง VBE immediates (aka VBE Debug Window) เป็นวิธีการส่งออกทั่วไปสำหรับ VBA สำหรับความท้าทายตามข้อความ แต่มันเป็นสิ่งสำคัญที่ต้องจำไว้ว่าDebug.Print "Text"การเรียกร้องอาจจะแข็งแรงเล่นกอล์ฟอย่างมีนัยสำคัญ

Debug.Print "Text"

มีหน้าที่เหมือนกับ

Debug.?"Text"

เป็น?autoformats Printไป

เอาต์พุตจากรูทีนSubและ VBE ฟังก์ชันหน้าต่างทันทีด้วยวิธีอื่น

ในโอกาสที่หายากเมื่อสถานการณ์มีความถูกต้องคุณอาจรับอินพุตจากอินพุตที่ไม่สำคัญของ VBA เช่นตัวปรับขนาดตัวอักษรตัวเลือกแบบอักษรและซูม (เช่นการเลียนแบบตัวเลือกขนาดแบบอักษรของ Word )


2

หมายเหตุด่วนเกี่ยวกับการฟอร์แมต

เนื่องจาก StackExchange ใช้Markdownและ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
เทย์เลอร์สกอตต์

2

If .. Thenตรวจสอบหลายรายการ

ในฐานะที่เป็นภาษาอื่น ๆ หลายIfการตรวจสอบสามารถจะรวมกันเป็นเส้นเดียวเพื่อให้สามารถใช้And/ Or(เช่น&&/ ||ใน C และอื่น ๆ ) ซึ่งใน VBA แทนที่ทั้งสองและThenEnd 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

This can become (51 chars):

If a = b Or c = b Then            
    d = 0
End If

1
in If - then statements the "End - if" part is optional provide you write the code in the single line.
Stupid_Intern

@newguy Correct. See also this other answer: codegolf.stackexchange.com/a/5788/3862
Gaffi

The statement above can be condensed further to d=iif(a=b or c=b,0,d)
Taylor Scott

2

Ending For Loops

When using For loops, a Next line does not need a variable name (though it is probably better to use in normal coding).

Therefore,

For Variable = 1 to 100
    'Do stuff
Next Variable

can be shortened to:

For Variable = 1 to 100
    'Do stuff
Next

(The savings depends on your variable name, though if you're golfing, that's probably just 1 character + 1 space.)


1
2 characters, don't forget to count the space!
11684

I happen to almost never identify the variable, even in normal code!
dnep

2

Split a string into a character array

Sometimes it can be useful to break apart a string into individual characters, but it can take a bit of code to do this manually in 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

Instead, you can use a single line, relatively minimal chain of functions to get the job done:

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

This will assign your string s to Variant array a. Be careful, though, as the last item in the array will be an empty string (""), which will need to be handled appropriately.

Here's how it works: The StrConv function converts a String to another format you specify. In this case, 64 = vbUnicode, so it converts to a unicode format. When dealing with simple ASCII strings, the result is a null character (not an empty string, "") inserted after each character.

The following Split will then convert the resulting String into an array, using the null character Chr(0) as a delimiter.

It is important to note that Chr(0) is not the same as the empty string "", and using Split on "" will not return the array you might expect. The same is also true for vbNullString (but if you're golfing, then why would you use such a verbose constant in the first place?).


You should mention that the resulting array has an additional empty string at the end.
Howard

@Howard Yes, I should. It was in my head while I was typing this up, must have slipped my mind.
Gaffi

2

Using With (Sometimes! See footnote)

Using the With statement can reduce your code size significantly if you use some objects repeatedly.

i.e. this (80 chars):

x = foo.bar.object.a.value
y = foo.bar.object.b.value
z = foo.bar.object.c.value

can be coded as (79 chars):

With foo.bar.object
    x = .a.value
    y = .b.value
    z = .c.value
End With

The above isn't even the best-case scenario. If using anything with Application, such as Excel.Application from within Access, the improvement will be much more significant.


*Depending on the situation, With may or may not be more efficient than this (64 chars):

Set i = foo.bar.object
x = i.a.value
y = i.b.value
z = i.c.value

2

Infinite Loops

Consider replacing

Do While a<b
'...
Loop

or

Do Until a=b
'...
Loop

with the antiquated but lower byte count

While a<b
'...
Wend

If you need to exit a Sub or Function prematurely, then instead of Exit ...

For i=1To 1000
    If i=50 Then Exit Sub
Next

consider End

For i=1To 1E3
    If i=50 Then End
Next

Note that End halts all code execution and clears out any global variables, so use wisely


You should consider rewriting the last section (For and End) to reflect that the case 100 will never be met and adds an unecessary byte
Taylor Scott

Also, while this is very legible, you may consider removing the whitespace to show the possible benefits of these methods better (it is always good to abuse the autoformatting in VBA for codegolfing)
Taylor Scott

2

Use Spc(n) over Space(n), [Rept(" ",n)] or String(n," ")

When trying to insert several spaces of length n, use

Spc(n)              ''  6  bytes

over

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

Note: I am not sure why, but it seems that you cannot assign the output of Spc(n) to a variable, and that it must rather be printed directly - so in certain cases Space(n) is still the best way to go.


2

Reduce Debug.Print and Print calls

Debug.Print [some value] 

(12 Bytes; note the trailing space) may be reduced to

Debug.?[some value]

(7 Bytes; note the lack of trailing space).

Similarly,

Print 

(6 Bytes) may be reduced to

?

(1 Byte).

Furthermore, when operating in the context of an anonymous VBE immediate window function the Debug statement may be dropped entirely, and instead printing to the VBE immediate window via ? may be assumed to be STDIN/STDOUT

Special characters

When printing strings you can also use special characters in place of &. These allow for alternate formats in what's printed or whitespace removal

To join variable strings, instead of

Debug.Print s1 &s2

You can use a semicolon ;

Debug.?s1;s2

This semicolon is the default behaviour for consecutive strings, as long as there is no ambiguity So these are valid:

Debug.?s1"a"
Debug.?"a"s1

But not

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

Note that a ; at the end of a line suppresses a newline, as newlines are by default added after every print. Counting bytes returned by VBA code is under debate

To join with a tab use a comma , (actually 14 spaces, but according to )

Debug.?s1,s2 'returns "s1              s2"

Finally, you can use type declarations to join strings instead of ;, each having its own slight effect on formatting. For all of the below a = 3.14159 is the first line

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

Use a helper Sub to Print

If the code requires using more than six Debug.? statements you can reduce bytes by replacing all Debug.? lines with a call to a Sub like the one below. To print a blank line you need to call p "" since a parameter is required.

Sub p(m)
Debug.?m
End Sub

1
To print a new line with that you would only need p"" or if it can be unterminated, p". However, in the vast majority of cases where this may apply, it makes more sense to use a string variable and only print the string variable at the end.
Taylor Scott

1

Use Array() Choose() instead of Select or If...Then

When assigning a variable based on a the value of another variable, it makes sense to write out the steps with If...Then checks, like so:

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

However, this can take up a lot of code space if there are more than one or two variables to check (there are still generally better ways to do even that anyway).

Instead, the Select Case statement helps reduce the size of the checks by encasing everything in one block, like so:

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

This can lead to much smaller code, but for very simple cases such as this, there is an even more efficient method: Choose() This function will pick a value from a list, based on the value passed to it.

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

The option to select (a in this case) is an integer value passed as the first argument. All subsequent arguments are the values to choose from (1-indexed, like most VBA). The values can be any data type so long as it matches the variable being set (i.e. objects don't work without the Set keyword) and can even be expressions or functions.

b = Choose(a, 5 + 4, String(7,"?"))

An additional option is to use the Array function to get the same effect while saving another character:

b = Array(5 + 4, String(7,"?"))(a)

An interesting and possibly very beneficial use for golfing is to use this in conjunction with an IIf() or another 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

Bit-Shifted RGB Values

Because of the way that Excel handles colors, (unsigned, 6-character hexadecimal integer) you can make use of negatively signed integers, of which excel will only use the right 6 bytes to assign a color value

This is a bit confusing so some examples are provided below

Lets say you want to use the color white, which is stored as

rgbWhite

and is equivalent to

&HFFFFFF ''#value: 16777215

to golf this down all we need to do is find a negative hexadecimal value which terminates in FFFFFF and since negative Hex values in must be in the format of FFFFXXXXXX (such that X is a valid hexadecimal) counting down from FFFFFFFFFF (-1) to FFFF000001 (-16777215)

Knowing this we can generalize that the formula

Let Negative_Color_Value = -rgbWhite + Positive_Color_Value - 1
                         = -16777215 + Positive_Color_Value - 1
                         = -16777216 + Positive_Color_Value

Using this, some useful conversions are

rgbWhite = &HFFFFFF = -1 
rgbAqua  = &HFFFF00 = -256
16747627 = &HFF8C6B = -29589

Good to know what was going on there, I just discovered it by accident in that question - but this clear explanation shows exactly how it works. Another thing to bear in mind is that certain key colours can be reduced with mathematical operators; rgbWhite=2^24-1 although could possibly be reduced further if you miss off the -1 to get roughly there
Greedo

1
In fact, here is a list of colours with their mathematical representations, which are shorter than either the positive or negative decimal versions: &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 n.b. not necessarily complete, but I think I did a fairly thorough job
Greedo

1

Omit terminal " when printing to Immediate Window

Given the function below, which is to be used in the debug window

h="Hello":?h", World!"

The Terminal " may be dropped for -1 Byte, leaving the string unclosed and the program shall execute the same, without error

h="Hello":?h", World!

Even more surprising than this is that this may be done within fully defined subroutines.

Sub a
h="Hello":Debug.?h", World!
End Sub

The subroutine above runs as expected and autoformats to

Sub a()
h = "Hello": Debug.Print h; ", World!"
End Sub

1

Use Truthy and Falsey Variables in conditionals

Sometimes called implicit type conversion - directly using a number type in a If,[IF(...)] or IIf(...) statement, by using the truthy and falsey nature of that number can absolutely save you some bytes.

In VBA, any number type variable that is non-zero is considered to be truthy ( and thus zero, 0, is the only value falsey) and thus

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

may be condensed to

If B Then C=B Else C=D

and further to

C=IIf(B,B,D)

1

Address Sheets By Name

Instead of Addressing a WorkSheet object by calling

Application.ActiveSheet
''  Or 
ActiveSheet   

One may use

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

Or More preferably one may access the object directly and use

Sheet1

1

Exponentiation and LongLongs in 64-Bit VBA

The general form of exponentiation,

A to the power of B

Can be represented as in VBA as

A^B 

But Only in 32-Bit Installs of Office, in 64-Bits installs of Office, the shortest way that you may represent without error this is

A ^B

This is because in 64-Bit versions of VBA ^ serves as both the exponentiation literal and the LongLong type declaration character. This means that some rather odd-looking but valid syntax can arise such as

a^=2^^63^-1^

which assigns variable a to hold the max value of a Longlong


1

Compress Byte Arrays as String

For challanges that require the solution to hold constant data, it shall may be useful to compress that data as a single string and to then iterate across the string to fetch the data.

In VBA, any byte value may be directly converted to a character with

Chr(byteVal)

And a long or integer value may be converted to two characters with

Chr(longVal / 256) & Chr(longVal Mod 256)

So for a byte array a compression algorithm would look something like

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$

Noting that the Select Case section is implemented due to the characters which may not be stored as literals in the string.

From the resulting string, which will look something like

t="5¼-™):ó™ˆ"+vbTab+"»‘v¶<®Xn³"+Chr(0)+"~ίšÐ‘š;$ÔÝ•óŽ¡¡EˆõW'«¡*{ú{Óx.OÒ/R)°@¯ˆ”'®ïQ*<¹çu¶àªp~ÅP>‹:<­«a°;!¾y­›/,”Ì#¥œ5*B)·7    

The data may then be extracted using the Asc and Mid functions, eg

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

1

Use Improper Constants

VBA allows, in some cases, for the use of unlisted or improper constants in expressions which require constant values. These are often legacy values, and shorter in length than the proper values.

For example the values below may be used when letting a value be held by the rng.HorizantalAlignment property.

ImproperProperGeneral ConstantxlHAlign  Constant11xlGeneralxlHAlignGeneral24131xlLeftxlHAlignLeft34108xlCenterxlHAlignCenter44152xlRightxlHAlignRight55xlFillxlHAlignFill64130xlJustifyxlHAlignJustify77xlCenterAcrossSelectionxlHAlignCenterAcrossSelection84117xlDistributedxlHAlignDistributed

This means, for example that setting a cell to having its text centered with

rng.HorizantalAlignment=-4108

may be shortened down to

rng.HorizantalAlignment=3

by replacing the improper constant value 3 for the proper value -4108. Note that if you fetch the rng.HorizantalAlignment property value, it will return the proper value. In this case, that would be -4108.


1

In Excel, Create Numeric Arrays by Coercing Ranges

When a constant single dimensional set of numerics of mixed length, S is needed, it shall be more efficient to use [{...}] notation to declare a range and then coerce that into a numeric array rather than to use the Split(String) notation or similar.

Using this method, a change of Δbyte count=5 bytes shall be accrued for all S.

Example

For instance,

x=Split("1 2 34 567 8910")

may be written as

x=[{1,2,34,567,8910}]

It is further worth noting that while this method does not allow for direct indexing, it does allow for iteration over the for loop directly, ie

For Each s In[{1,3,5,7,9,2,4,6,8}]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.