ฉันจะประกาศตัวแปรส่วนกลางใน VBA ได้อย่างไร


132

ฉันเขียนรหัสต่อไปนี้:

Function find_results_idle()

    Public iRaw As Integer
    Public iColumn As Integer
    iRaw = 1
    iColumn = 1

และฉันได้รับข้อความแสดงข้อผิดพลาด:

"แอตทริบิวต์ที่ไม่ถูกต้องใน Sub หรือ Function"

คุณรู้ไหมว่าฉันทำอะไรผิด?

ฉันพยายามใช้GlobalแทนPublicแต่มีปัญหาเดียวกัน

ฉันพยายามประกาศว่าฟังก์ชันนี้เป็นสาธารณะ แต่ก็ไม่ดีเช่นกัน

ฉันต้องทำอย่างไรเพื่อสร้างตัวแปรส่วนกลาง

คำตอบ:


177

คุณต้องประกาศตัวแปรนอกฟังก์ชัน:

Public iRaw As Integer
Public iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1

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

ดังกล่าวข้างต้นแรกFunction/ Subไม่นอก: "ตัวแปรระดับโมดูลสามารถประกาศกับติ่มหรือส่วนตัวคำสั่งที่ด้านบนของโมดูลดังกล่าวข้างต้นความละเอียดขั้นตอนแรก." (จากขอบเขตของตัวแปรใน Visual Basic for Applications )
Nickolay

119

นี่คือคำถามเกี่ยวกับขอบเขต

หากคุณต้องการให้ตัวแปรมีอายุการใช้งานของฟังก์ชันเท่านั้นให้ใช้Dim(ย่อมาจากDimension ) ภายในฟังก์ชันหรือย่อยเพื่อประกาศตัวแปร:

Function AddSomeNumbers() As Integer
    Dim intA As Integer
    Dim intB As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are no longer available since the function ended

โลกตัวแปร (ตาม SLaks ชี้ให้เห็น) ประกาศด้านนอกของฟังก์ชั่นการใช้Publicคำหลัก ตัวแปรนี้จะพร้อมใช้งานในช่วงอายุของแอปพลิเคชันที่คุณกำลังทำงานอยู่ ในกรณีของ Excel หมายความว่าตัวแปรจะพร้อมใช้งานตราบเท่าที่สมุดงาน Excel นั้นเปิดอยู่

Public intA As Integer
Private intB As Integer

Function AddSomeNumbers() As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are still both available.  However, because intA is public,  '
'it can also be referenced from code in other modules. Because intB is private,'
'it will be hidden from other modules.

นอกจากนี้คุณยังสามารถมีตัวแปรที่สามารถเข้าถึงได้ภายในโมดูลเฉพาะ (หรือคลาส) โดยการประกาศด้วยไฟล์ Privateคีย์เวิร์ด

หากคุณกำลังสร้างแอปพลิเคชันขนาดใหญ่และรู้สึกว่าจำเป็นต้องใช้ตัวแปรส่วนกลางฉันขอแนะนำให้สร้างโมดูลแยกเฉพาะสำหรับตัวแปรส่วนกลางของคุณ สิ่งนี้จะช่วยให้คุณติดตามพวกเขาได้ในที่เดียว


4
+1 ยังคงมีประโยชน์ใน 7 ปีต่อมา แต่มีความแตกต่างเล็กน้อยเพิ่มเติมเกี่ยวกับตัวแปรออบเจ็กต์เทียบกับตัวแปรข้อมูลหรือไม่? ฉันพบปัญหาที่เกี่ยวข้องกับตัวแปรออบเจ็กต์การกำหนดขอบเขตที่ทำให้เกิดคำถามใหม่ ชื่นชมมากถ้าคุณมีเวลาดู stackoverflow.com/q/46058096/5457466
Egalth

2
คำอธิบายที่ชัดเจนของการประกาศตัวแปรใน VBA
PhillipOReilly

ฉันลองทำตามคำแนะนำอื่น ๆ เกี่ยวกับ "ขอบเขต" แล้ว แต่ก็ไม่มีผล สิ่งเดียวที่ใช้งานได้คือโมดูลใหม่สำหรับตัวแทนทั่วโลกโดยเฉพาะและใช้งานได้!
Fandango68

34

หากต้องการใช้ตัวแปรส่วนกลางให้แทรกโมดูลใหม่จาก VBA Project UI และประกาศตัวแปรโดยใช้ Global

Global iRaw As Integer
Global iColumn As Integer

2
อะไรคือความแตกต่างระหว่างการประกาศด้วยPublicvs ด้วยGlobalคำหลัก?
Przemyslaw Remin


18

คำถามนั้นเกี่ยวกับขอบเขตจริงๆอย่างที่อีกคนวางไว้

กล่าวโดยย่อให้พิจารณา "โมดูล" นี้:

Public Var1 As variant     'Var1 can be used in all
                           'modules, class modules and userforms of 
                           'thisworkbook and will preserve any values
                           'assigned to it until either the workbook
                           'is closed or the project is reset.

Dim Var2 As Variant        'Var2 and Var3 can be used anywhere on the
Private Var3 As Variant    ''current module and will preserve any values
                           ''they're assigned until either the workbook
                           ''is closed or the project is reset.

Sub MySub()                'Var4 can only be used within the procedure MySub
    Dim Var4 as Variant    ''and will only store values until the procedure 
End Sub                    ''ends.

Sub MyOtherSub()           'You can even declare another Var4 within a
    Dim Var4 as Variant    ''different procedure without generating an
End Sub                    ''error (only possible confusion). 

คุณสามารถตรวจสอบข้อมูลอ้างอิง MSDNนี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการประกาศตัวแปรและคำถาม Stack Overflowอื่น ๆสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการที่ตัวแปรออกนอกขอบเขต

อีกสองสิ่งที่รวดเร็ว:

  1. จัดระเบียบเมื่อใช้ตัวแปรระดับสมุดงานเพื่อให้โค้ดของคุณไม่สับสน ต้องการฟังก์ชั่น (กับชนิดข้อมูลที่เหมาะสม) หรือข้อโต้แย้งที่ผ่านByRef
  2. หากคุณต้องการให้ตัวแปรรักษาค่าระหว่างการโทรคุณสามารถใช้คำสั่งStatic

คุณแน่ใจหรือไม่ว่าตัวแปร Global สามารถใช้ในสมุดงานอื่นได้ ไม่ได้ผลสำหรับฉัน
Seb

จุดดี! ฉันสังเกตว่าฉันไม่ได้เพิ่มข้อมูลอ้างอิงว่าฉันได้ข้อมูลนั้นมาจากที่ใด ... และฉันไม่พบอีกเลย แก้ไขคำตอบดีกว่า ... : / อ้อและขอบคุณ Seb
FCastro

14

หากฟังก์ชั่นนี้อยู่ในโมดูล / Global Scopeชั้นคุณก็สามารถเขียนไว้ด้านนอกของฟังก์ชั่นจึงมี Global Scope หมายถึงตัวแปรสามารถเข้าถึงได้โดยฟังก์ชันอื่นในโมดูล / คลาสเดียวกัน (หากคุณใช้dimเป็นคำสั่งประกาศให้ใช้publicถ้าคุณต้องการให้ตัวแปรสามารถเข้าถึงได้โดยฟังก์ชันทั้งหมดในโมดูลทั้งหมด):

Dim iRaw As Integer
Dim iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1
End Function

Function this_can_access_global()
    iRaw = 2
    iColumn = 2
End Function

1

สร้างจำนวนเต็มสาธารณะใน General Declaration

จากนั้นในฟังก์ชันของคุณคุณสามารถเพิ่มมูลค่าได้ทุกครั้ง ดูตัวอย่าง (ฟังก์ชันบันทึกไฟล์แนบของอีเมลเป็น CSV)

Public Numerator As Integer

Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim FileName As String

saveFolder = "c:\temp\"

     For Each objAtt In itm.Attachments
            FileName = objAtt.DisplayName & "_" & Numerator & "_" & Format(Now, "yyyy-mm-dd H-mm-ss") & ".CSV"
                      objAtt.SaveAsFile saveFolder & "\" & FileName
                      Numerator = Numerator + 1

          Set objAtt = Nothing
     Next
End Sub

0

วิธีที่ดีในการสร้างตัวแปร Public / Global คือการปฏิบัติต่อ Form เหมือนคลาสออบเจ็กต์และประกาศคุณสมบัติและใช้ Public Property Get [ตัวแปร] เพื่อเข้าถึงคุณสมบัติ / วิธีการ นอกจากนี้คุณอาจต้องอ้างอิงหรือส่งการอ้างอิงไปยังโมดูลฟอร์มที่สร้างอินสแตนซ์ คุณจะได้รับข้อผิดพลาดหากคุณเรียกวิธีการไปยังแบบฟอร์ม / รายงานที่ปิดอยู่
ตัวอย่าง: ส่ง Me.Form.Module.Parent เป็น sub / function ไม่อยู่ในฟอร์ม

Option Compare Database 
Option Explicit
''***********************************''
' Name: Date: Created Date Author: Name 
' Current Version: 1.0
' Called by: 
''***********************************''
' Notes: Explain Who what when why... 
' This code Example requires properties to be filled in 
''***********************************''
' Global Variables
Public GlobalData As Variant
''***********************************''
' Private Variables
Private ObjectReference As Object
Private ExampleVariable As Variant
Private ExampleData As Variant
''***********************************''
' Public properties
Public Property Get ObjectVariable() As Object
   Set ObjectVariable = ObjectReference
End Property 
Public Property Get Variable1() As Variant 
  'Recommend using variants to avoid data errors
  Variable1 = ExampleVariable
End property
''***********************************''
' Public Functions that return values
Public Function DataReturn (Input As Variant) As Variant
   DataReturn = ExampleData + Input
End Function 
''***********************************''
' Public Sub Routines
Public Sub GlobalMethod() 
   'call local Functions/Subs outside of form
   Me.Form.Refresh
End Sub
''***********************************''
' Private Functions/Subs used not visible outside 
''***********************************''
End Code

ดังนั้นในโมดูลอื่นคุณจะสามารถเข้าถึงได้:

Public Sub Method1(objForm as Object)
   'read/write data value
   objForm.GlobalData
   'Get object reference (need to add Public Property Set to change reference object)
   objForm.ObjectVariable
   'read only (needs Public property Let to change value)
   objForm.Variable1
   'Gets result of function with input
   objForm.DataReturn([Input])
   'runs sub/function from outside of normal scope
   objForm.GlobalMethod
End Sub

ถ้าคุณใช้ Late Binding เช่นฉันมักจะตรวจสอบค่า Null และวัตถุที่ไม่มีอะไรก่อนที่จะพยายามประมวลผลใด ๆ


0

นอกจากนี้คุณสามารถใช้ -

Private Const SrlNumber As Integer = 910

Private Sub Workbook_Open()
    If SrlNumber > 900 Then
        MsgBox "This serial number is valid"
    Else
        MsgBox "This serial number is not valid"
    End If
End Sub

ผ่านการทดสอบใน office 2010

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.