How to Use VBA - PowerPoint PPT Presentation

1 / 113
About This Presentation
Title:

How to Use VBA

Description:

Can hide any tricks being used to call into the c code. ( Strings are a bit tricky/weird/magic. ... Keeps all the tricks in one place to prevent argument ... – PowerPoint PPT presentation

Number of Views:410
Avg rating:3.0/5.0
Slides: 114
Provided by: wwwpp
Learn more at: https://www-ppd.fnal.gov
Category:

less

Transcript and Presenter's Notes

Title: How to Use VBA


1
How to Use VBA Excel with the Bit3 to VME
  • R. Angstadt
  • March, 5 2004

2
Why VBA? Why not VB? C?Great Glue Language
  • VBAVisual Basic (for) Applications. VBVisual
    Basic is a standalone product that must be
    purchased separately. (VB(A) indicates
    features common to both!) VBA comes with Excel
    so there is no extra cost. If you are running
    some version of windows with Office installed
    then it is on your machine now! VB(A) allows
    reuse of the million(s) of lines of C code that
    Excel is written in to be reused. It provides an
    easy way to re-use code. No building of custom
    forms are required because it is so easy to use a
    Worksheet as a pre-defined form its usually not
    worth the trouble to make a custom one!
  • a. VBA knows about and can access all of
    the functions in Excel either natively or using
    the function Application.ExecuteExcel4Macro
    (an_Excel_Function_Here!) VBA runs in
    Excels context/scope. VBA can access 99.9 of
    all the Excel menus and any objects, methods or
    functionality they perform.
  • b. VB(A) can call almost any function of
    any DLL on your computer including Kernel calls,
    anything you write or someone else writes in
    other languages such as C and/or inline
    assembler. The DLL it calls into could also be a
    driver DLLs that goes to hardware! VBA and
    Excel are engineered to be extensible DDE, OLE,
    COM DCOM. Microsoft has published book on
    extending it. (Excel Developers Kits (various
    years) Book and disk(s) or CD.)
  • c. Spreadsheets analyze stock market quotes
    in real time and the original article Marvin read
    in EE times involved operating a Nuclear Reactor!

3
  • 2. VBA Excel Enables Rapid code
    prototyping/development
  • Saves lines of code! Engineered to be simpler
    than C. Savings can be as much as 40 lines of
    C to one VB line! A simple peek, poke real
    windows program all in C takes gt 1k lines
    excluding the Bit3 libraries/drivers. A Bit3
    list processor can be done in lt 100 lines
    excluding the same Bit3 libraries/drivers.
    Typical realized average savings in lines of code
    has been on the order of a factor of 10.
  • Saves person power The HV front panel
    application that took 6 to 8K lines of Pascal
    and 2-3 PERSON YEARS was done in 1,000 lines
    in 4 months. (In terms of lines saved for this
    project at least a factor of 6 (conservatively)
    or more in savings.)
  • 3. Originally suggested by M. Johnson as an
    easier way to move from DOS (Turbo Pascal) to
    Windows environment. (We actually tried
    something similar cerca 86 with Lotus 123 macros
    but it was not modular and hard to maintain and
    the screen flashed annoyingly.) VBA and Excel
    have overcome these deficiencies.

4
FYI only Before GetOpenFileName in C can be
called it takes 44 lines to fill the structure
call!
  • void PopFileInitialize (HWND hwnd)
  • static char szFilter "Data Files
    (.DAT)\0.dat\0" \
  • "Paint Files (.BMP)\0.bmp\0" \
  • "Text
    Files (.TXT)\0.txt\0" \
  • "All
    Files (.)\0.\0\0"
  • ofn.lStructSize sizeof
    (OPENFILENAME)
  • ofn.hwndOwner hwnd
  • ofn.hInstance NULL
  • ofn.lpstrFilter szFilter
  • ofn.lpstrCustomFilter NULL
  • ofn.nMaxCustFilter 0
  • ofn.nFilterIndex 0
  • ofn.lpstrFile NULL //
    Set in Open and Close functions
  • ofn.nMaxFile _MAX_PATH
  • ofn.lpstrFileTitle NULL //
    Set in Open and Close functions
  • ofn.nMaxFileTitle _MAX_FNAME
    _MAX_EXT
  • ofn.lpstrInitialDir NULL

5
File Dialoque Boxes in VBA takes a few lines.
  • Information can always be read or written to a
    file. Furthermore it can be done using the same
    file dialogue box Excel uses with just a few
    lines of VBA code. Here the whole get a file to
    read routine takes 14 lines. 2 lines for
    arguments 1 to make the call is 3 lines max.
  • Sub getFileNameVRB()
  • Dim szTitle As String
  • Dim szFilter As String
  • Dim szFileName As String
  • Dim szOKwasPressedNoCancel As String
  • ' Select a file to print, use the standard
    excel get a file dialogue box
  • szTitle "S record .hex file to process"
  • szFilter "S record .hex Files (.hex), .hex"
  • szOKwasPressedNoCancelApplication.GetOpenFilena
    me(FileFilterszFilter,TitleszTitle)
  • If szOKwasPressedNoCancel ltgt "False" Then
  • szFileName szOKwasPressedNoCancel
  • Cells(12, 4).Value szFileName could
    open it here and do something!
  • End If
  • End Sub 'getFileNameVRB
  • Heres the VBA help notes dialogue box for
    obtaining a file to write (save) to taking 1
    lines (plus 3 for error handling!).
  • fileSaveName Application.GetSaveAsFilename( _
    fileFilter"Text Files (.txt), .txt")

6
VBA has been Modernized!
  • Line numbers obsolete (though still supported!)
    Its now a modern language with block structure
    concepts like Pascal and C including Case
    statements. Has modules (ala Modulo), arguments
    passed by reference by default (like Fortran so
    arrays can be passed like many are used to. )
  • Has a very nice IDE (Integrated Development
    Environment (ala Borland Turbo Pascal) with
    editor and real debugger, and context sensitive
    help.
  • Has Short Comings but is Quite Useable. Any
    shortcomings can usually be worked around and/or
    overcome with some C code in a DLL! No show
    stoppers so far!
  • It has maintained its backward compatibility
    very well. (Old code has not been broken. Of
    course macro recording on say Version 10.x and
    then running on Version 9.x may not work! Have
    to record on Version 9.x and run on Version
    10.x!) (Even includes code from some early DOS
    versions as per Craig Symonds in 96 Group
    Programmer Manager for the VB group (VB, VBA, and
    scripting for last 5 years from 96. (pg xxx of
    VBA Developers Handbook, Sybex 97 by K. Getz
    M. Gilbert.) I can verify this as one time I used
    an old function IBM DOS function from an IBM
    Basic manual that I had laying around but was not
    Microsofts help at the time. When I typed it in
    it ran! (Integer is still 16 bits even after
    they ported it from a 16 bit version to a 32 bit
    version!)
  • Will try to not speak too much about operating
    systems as its almost a moot point here but it
    will be unavoidable at some point so I would like
    to explain the following right now in the
    beginning.
  • Win 9x shall mean Windows 95, (OSR2), Windows
    98 (1 and 2) through ME (Millennium Edition)
    because from the stand point of most driver
    development including my Bit 3 drivers they are
    the same. (Same driver for all of them!)
  • Likewise, NT shall also include Win2k, and XP
    in a generic sense as they all use basically the
    same driver model which is of course is a
    completely different driver model from 1 above.
    Win 9x and NT were developed by two completely
    different programmer teams with different
    design goals and emphasis even thought they are
    from the same company so they are really pretty
    different operating systems. Though they share
    some components, their code base is different.
    Go to File Explorer, Help, About in each
    and you will see NT is Release 4 (Service pack
    6) Win2k is Release 5.0 (Service pack 3) and
    XP is (only) Release 5.1. So except for
    marketing and hype they are all still basically
    NT. The same goes for driver model. The same
    Bit3 driver of mine almost works on all of them
    except for XP which requires a tweak and has its
    own version. (Havent tried the XP tweak on
    Win2k and/or XP.) Thus, NT shall mean any and all
    of NT, Win2k, or XP unless XP or Win2k are
    specifically mentioned.

7
Our First VBA program!
  • The key combo Alt-F11 brings up the VBA IDE. (If
    not then Tools, Macro, Visual Basic Editor)
    brings it up. (Many ways to get back to Excel
    including Alt-F11.
  • On the VB IDE click on Insert and then Module
    and Module1 comes up in the property box. In
    the largest white area type in
  • Sub hello()
  • Cells(1, 1).Value "hello world"
  • End Sub
  • Go back to Excel (Alt-F11) and run it. Various
    ways but Alt-F8 works! And then run! hello
    world appears in upper left hand corner cell
    A1. Not so exciting by itself. But it could
    be put anyplace on the screen by changing the 1,1
    to any row numbers of 1 to 65536 and the column
    number from 1 to 255. Also note that cells
    ends in an s (plural.) This is intentional and
    signals it is an array and/or collection. For
    arrays and/or collections within Excel this is
    amazingly consistent! The . is an separator for
    objects and/or methods. Thus object.sub_object_ch
    ild1sub_object_n.final_object_or_method is
    typical syntax. More and better concrete
    examples to follow.

8
CountWrite our 2nd Subroutine!
  • Slightly more exciting is
  • Sub count2Ten()
  • Dim lRow As Long
  • For lRow 1 To 10
  • Cells(lRow, 1).Value lRow
  • Next lRow
  • End Sub
  • Although it is not required to declare
    everything, it is a good idea to do so. Putting
    Option Explicit at the top of the module
    requires that you declare everything.
  • Another thing that is good to get in the habit of
    doing is after you make an edit in the VBA IDE is
    to go to the Debug menu pick and then
    Compile. One good reason to do this is that if
    you are just making a small change it may not be
    seen by VBA so the Compile will be grayed out!
    For example if you go to the 10 and type in 5 and
    then go run the macro chances are it will do the
    loop 10 times. To remedy this one must move the
    cursor off the line and/or go to the end of a
    line and hit the Enter key (it adds a blank
    line, you can delete it if you want!). But the
    point of all this is to make some changes in the
    code that it will see so that the Compile will
    not be grayed out. While some interpretation is
    done while you type, Compiling does a lot more
    including (argument) type checking of the whole
    project. Its just a good idea and may save you
    having to come back and add a Dim statement as
    well as possibly helping to keep the Worksheet
    file size minimal. Also when the button is
    pushed there will be lower latency the first time
    as it wont have to automatically compile it
    first (assuming it was a big enough change that
    it saw) it will already have been compiled!

9
Our Third Puts Formulas in Sheet!
  • Sub Circumference()
  • 'puts formulas in the cells sheet can update
    immedietly when user types in a new radius!
  • Dim lAry(11) As Long
  • Dim lRow As Long
  • Dim lIndex As Long
  • 'put up some headers
  • Cells(1, 3).Value "Radius"
  • Cells(1, 5).Value "Circum Formulas!"
  • 'read output of sub count2Ten()
  • For lRow 1 To 10
  • lAry(lRow) Cells(lRow, 1).Value
  • Next lRow
  • 'make a little radius, circumference table
  • lIndex 1
  • For lRow 2 To 11

10
Circumference2 Just the Values!
  • Sub Circumference2()
  • ' another way all from code the macro must be
    re-run if any radi are changed! ignores user
    input!
  • Dim lAry(11) As Long
  • Dim lRow As Long
  • Dim lIndex As Long
  • Dim dPi As Double
  • 'put up some headers
  • Cells(1, 3).Value "Radius"
  • Cells(1, 7).Value "Circum Values Only"
  • 'read output of sub count2Ten()
  • For lRow 1 To 10
  • lAry(lRow) Cells(lRow, 1).Value
  • Next lRow
  • way cool calling an excel function from
    within VBA!
  • dPi Application.ExecuteExcel4Macro("Pi()")

11
Circumference 3 Using Functions
  • Sub Circumference3()
  • ' uses functions for better code reuse
  • Dim dAry(11) As Double
  • Dim lRow As Long
  • Dim lIndex As Long
  • Dim dPi As Double
  • 'put up some headers
  • Cells(1, 3).Value "Radius"
  • Cells(1, 9).Value "Circum Values Using
    Function calls in code"
  • 'read output of sub count2Ten()
  • For lRow 1 To 10
  • dAry(lRow) Cells(lRow, 1).Value
  • Next lRow
  • 'make a little radius, circumference table

12
User Written Functions called by Circumference3!
(can call from Excel!)
  • Function getPi() As Double
  • ' this is a way cool thing any function in
    excel you can call from vba!
  • ' pi() is an excel function returning pi to 15
    places its not intrinsic to vba!
  • getPi Application.ExecuteExcel4Macro("Pi()")
  • End Function
  • Function doCircum(dRadius As Double, dPi As
    Double) As Double
  • ' you can call this from another vba sub or
    function or right from excel!
  • ' if excel doesn't have a function you need you
    can write your own!
  • ' even making use of the functions built into
    excel.
  • doCircum 2 dRadius dPi
  • End Function

13
Icing on the (GUI) cake Buttons
  • Lets Make a button and assign it to a macro
    from Excel go to View, Toolbars and make sure
    Forms is clicked. Then click on the fourth
    object on the Forms toolbar which is a
    Button. Move the mouse to the Worksheet and
    press and hold down the left mouse button and
    drag it somewhere and release it.
  • Youve made Button 1 It can be attached
    directly to any subroutine (without arguments)
    that you write. Right click on it and attach it
    to one of the macros that we wrote earlier, say
    Circumference, change the text on the button,
    Button 1, to Circumference. Unselect the
    button by clicking anywhere on the sheet.
  • Now any time you left click on the button the
    Circumference macro will be run. It took 0
    code to make the button and assign it to the
    macro! Alternatively you could have done it all
    from code You can change its name or re-assign
    which macro it is run with at any time. Its all
    built into Excel.
  • Macros can be attached to many objects
    TextBoxes, Pictures, (.gifs) etc.
  • Note there are 2 buttons, (2 kinds of
    objects). Global and restricted (or local scope).
    (historically, old and new). I prefer the
    Global objects on the Forms button because I
    believe they are more useful one can attach them
    to generalized code that will work on the
    Active sheet. The other Control Toolbox
    buttons/objects are restricted and work only on
    the sheet they are attached to. They cant be
    copied to another sheet. Further pain is that
    they are edited in Design mode. (Sheet cannot
    be saved when in Design Mode) They are just one
    pain after another and I believe they should be
    avoided (like the plague.... Button from hell,
    etc. Youve been warned!)

14
Subroutines and Functions Which when?
  • Though Functions can return something in a cell
    when they are placed in a cell they generally can
    NOT in any way act on the screen e.g. cant use
    Cells(row,col).Value in a function to write to
    the sheet. (Must use a Sub) Also
  • Function try2callExcel4(szS As String)
  • 'if szs"zoom(75)" it doesn't zoom the screen
    because a function can NOT act on the screen
  • Application.ExecuteExcel4Macro szS
  • End Function
  • Sub zoom()
  • ' however this changes the screen size of the
    active sheet!
  • Application.ExecuteExcel4Macro "ZOOM(75)"
  • End Sub
  • If something doesnt work in a function try a
    sub!
  • Functions can NOT be hooked to a button or other
    object. (Must use a Sub). (Also if a
    subroutine has arguments it cannot be attached to
    a button directly. So to test a generalized
    module (with arguments) must write a Test module
    to call the generalized module. Sometimes
    referred to as a shell sub or just shell.)
  • But functions can be put in a cell and return a
    value! (Sub can NOT.)

15
Real Power, Importing External Functions in DLLs!
  • VB(A) has the ability to Register any external
    function in any DLL (Dynamic Link Library) on
    your computer. This DLL could ultimately be
    connected through a driver to hardware! This can
    be as general or as specific as the DLL and
    driver it connect to. Dont get thrown by DLL.
    It just means that the address of an external
    (object, binary or library) function is found,
    resolved, loaded, and executed (run) dynamically
    when called by a Click of a button somewhere or
    by some piece of code doing something! This is
    in contrast to the older more typical Static
    Library that is linked to at Code Compile and
    Link time. Win9x and NT are both almost entirely
    based on modules of (typically C) code which
    can call into each other back and forth by the
    mechanism(s) of dynamic loading and linking
    (DLL)! What it allows is just a code module
    (DLL) to be recompiled and/or replaced (as long
    as no entry points are deleted or no arguments of
    functions have been reduced. Their can be more
    functions but not less.) It also saves having to
    recompile the (whole) kernel. One just has to
    recompile that DLL which may or may not be part
    of the Kernel.
  • For our first example of registering and
    calling an external DLL well go right for the
    maximum gusto! Remember when Basics of yore
    included peek and poke (ing) to hardware?
    This is now once again made possible on NT if
    Dale Roberts clever driver giveio.sys is
    installed. (Win 9x needs no driver, just a
    similar DLL!) (For more about this see DDJ May
    96. Port I/O under Windows and NT Dales
    driver also saves a few hundred clocks of NT CPU
    time each time a peek or poke is made so that
    NT is now as fast as Win9x!) The old (and new)
    Peek() and Poke() routines allow one to get out
    on both the ISA and PCI buses via the
    motherboards chipset(s) to physical address 0 to
    65535 in I/O space. On Intel 86 (all my stuff
    is only for Wintel platform no other CPU is
    supported and only 1 CPU at that!) there is
    actually a physical CPU pin labeled I/O! When
    this pin (bit) is high then the address on the
    bus is to I/O. When not high its a normal
    (non-I/O) address. (Basically a 1 bit address
    modifier instead of VMEs 6 bit address
    modifier.) If NT is like eating at McDonalds
    and Win98 is like eating at Burger King then this
    driver allows us to eat at McDonalds and have it
    (our) way! With this one can be destructive and
    corrupt your hard drive or you can be
    constructive and get to the Parallel Port
    directly or talk directly to CAMAC via an ISA bus
    DSP card board set written entirely in VBA?
    (Used in the village and else where.). (The NT
    Bit3 DLL is as fast as it is partly due to this
    driver.) The DLL is on d0server4\users\angstadt\
    ntuitl\ntio\debug\ntio.dll Giveio.sys install
    instructions are on the web
  • http//d0server1.fnal.gov/users/angs
    tadt/www/b3/b3_61x.htm

16
Real Power, Importing External Functions in
DLLs! (2)
  • There is a similar DLL and driver for normal
    non-I/O memory as well d0server4\users\angstadt\n
    tuitl\ntphsad\debug\ntphsad.dll so with these 2
    drivers and DLL one can get to the hardware of
    their machine on a Virtual Operating System.
    Drivers may be written entirely in VBA!
  • Peeking probably wont hurt your machine too much
    but (RANDOM) Poking is STRONGLY discouraged!
  • So here it finally is the VBA code modNT_IO.
    Copy and paste it in to your spreadsheet or use
    d0server4\users\angstadt\ntutil\ntio.xls once
    giveio.sys is installed. Lets be careful out
    there! I/O address 0x200 is nominally safe as
    it is nominally the game port. However your
    machine may be different and/or not have one.
    Reading 0xff back is essentially not there, not
    initied, or in VME speak, NO DTACK. I/O
    address 0x378 is nominally LPT1 but this depends
    on the BIOS and Ports, Resources in the
    Device Manager of the Control Panel. Your
    mileage will definitely vary. Finally this is
    the VB(A) code
  • Declare Function pokeport Lib "ntio.DLL" (iAdd As
    Integer, iVal As Integer) As Integer
  • Declare Function peekport Lib "ntio.DLL" (iAdd As
    Integer) As Integer
  • Function VB_pokeIO(iAdd As Integer, iVal As
    Integer) As Integer
  • Dim i As Integer
  • i pokeport(iAdd, iVal)
  • VB_pokeIO i
  • End Function
  • Function VB_peekIO(iAdd As Integer) As Integer
  • Dim i As Integer
  • i peekport(iAdd)
  • VB_peekIO i
  • End Function

17
The C code the VBC calls
  • Part of ntio.c (so simple I didnt make a
    ntio.h file. (Shame on me.) Normally the .h
    file is what one looks at to register (import)
    C DLLs into VB(A) as above.) If I did have a
    ntio.h file it would have about 2 lines in it
  • DLLEXPORT short int WINAPI pokeport(long
    plportadd, long plval)
  • DLLEXPORT short int FAR PASCAL
    peekport(long plportadd)
  • The .h file is supposed to hold the function
    declarations that are exported so other modules
    can include the .h file so that they may
    (static) link to it at compile time. I
    (unfortunately must have been in a hurry) and
    skipped making a .h file. I evidently only
    cared about the VB(A) dynamic part. Below is the
    relevant part of ntio.c
  • DLLEXPORT short int WINAPI pokeport(long
    plportadd, long plval)
  • //writes ival to the p.c. port address specified
    by plportadd.
  • int ilocalval
  • unsigned short wadd
  • ilocalval(int) plval
  • wadd(unsigned short) plportadd 0xffff
  • return _outp(wadd,ilocalval)
  • //-----------------------------------------------
    ----------------------------
  • DLLEXPORT short int FAR PASCAL peekport(long
    plportadd)
  • //reads a value, itemp, from the p.c. port
    address specified by plportadd.

18
FYI MOST OF THE WHOLE NTIO.C DLL SOURCE clipped
some commentsALSO IS AN EXAMPLE OT WHAT EXCEL
SAVES YOU FROM! (FYI only. No quiz on this.)
  • .
  • include ltwindows.hgt
  • // include ltc\cpp\xlcall.hgt nothing from this
    really used
  • include ltstdio.hgt
  • include ltconio.hgt // macro def for port i/o
    outp is in conio.h
  • include ltdos.hgt
  • // include ltalloc.hgt // nec. for malloc()
  • include ltprocess.hgt // nec. for exit()
  • include ltstring.hgt
  • // include ltmath.hgt
  • //true defined in windows.h and other places
  • //define FALSE 0
  • //define TRUE 1
  • HANDLE hDriver
  • / gets called at load time...when the function
    is "registered". /
  • / main entry point /
  • BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD
    fdwReason, LPVOID lpvReserved)

19
  • //printf("Couldn't access giveio device\n")
  • bretFALSE
  • else
  • bretTRUE
  • //giveio modifies the i/o permission map in
    this task's tss
  • // task segment selector (according to the
    author) so
  • // once this is done, it's done! when the last
    dll user goes so
  • // does the task and it's permission map so we
    don't need giveio.sys
  • // anymore! (very very nice!) no cpu cycles
    are used on nt protection!
  • CloseHandle(hDriver)
  • break
  • case DLL_PROCESS_DETACH
  • // The DLL is being unloaded by a
    given process. Do any

20
  • // A thread is exiting cleanly in a
    process that has already
  • // loaded this DLL. Perform any
    per-thread clean up here. The
  • // return value is ignored.
  • bretTRUE
  • break
  • return bret
  • define DLLEXPORT __declspec(dllexport)
  • // this is the meat and potatoes
  • //-----------------------------------------------
    ----------------------------
  • DLLEXPORT short int WINAPI pokeport(long
    plportadd, long plval)
  • //writes ival to the p.c. port address specified
    by iportadd.
  • int ilocalval
  • unsigned short wadd
  • ilocalval(int) plval
  • wadd(unsigned short) plportadd 0xffff

21
Call the Kernel from VBA! This is modTime in
some sheets (VB(A)) code!
  • Public Declare Function timeGetTime Lib
    "winmm.dll" () As Long
  • Declare Sub Sleep Lib "Kernel32.DLL" (ByVal
    dwMillisecconds As Long)
  • Const lSLEEPTIME As Long 12 'milliseconds
  • Sub AbenchRead()
  • Dim l As Long
  • Dim lTime As Long
  • Dim lPlace As Long
  • Dim ival As Integer
  • Const lMAX As Long 1000
  • Const lAdd As Long 33536 '"H8300" -gt a
    neg. num!
  • 'MsgBox (" get ready to set your stop watch")
  • lTime getTimerVal
  • For l 1 To lMAX
  • ival VB_readi(lAdd)
  • Next l
  • lTime getTimerVal - lTime
  • MsgBox (" done reading " Format(lMAX) "
    times took " Format(lTime) " milliseconds ")
  • End Sub

22
Registering Bit3 DLL Functions! (some)
registered functions
  • 'have managed to unmangle the names for the 617
    driver!
  • '
  • Declare Function initio Lib "bntdv617.dll" (i As
    Integer, l As Long) As Integer
  • ' Besides initing the bit3, setting the address
    modifier, it initializes all
  • ' secondary error handling bite.dll flags to the
    correct state including
  • ' the internal static variable "abortflg"0
    false (no failures) or 1 a failure
  • Declare Function islatcherri Lib "bntdv617.dll"
    () As Integer
  • 'returns true1a failure if a bit3 error
    detected since the last time
  • 'initio() or clrlatcherri() was called. call
    getlasterrps() to find last error!
  • Declare Function clrlatcherri Lib "bntdv617.dll"
    () As Integer
  • ' set static variable "abortflg" to 0 false no
    failures and should always return 0.
  • ' the "c" code is
  • ' abortflgFALSE
  • ' return abortflg
  • Declare Function getlasterrps Lib "bntdv617.dll"
    (ByVal s As String) As Integer
  • ' tells what the last bit3 error was in english
    (more or less).
  • ' this is a noteworthy example of how to return
    call a "c" function that
  • ' returns a pointer to a null terminated string
    which VBasic has troubles with.
  • ' the "byval" fixes the null terminated part but
    it still has trouble with the pointer so

23
Bit3 Some Registered Functions Wrapped
  • Function VB_InitIOi(addmod As Integer, Address As
    Long, model406flg As Boolean) As Integer
  • Dim i As Integer
  • Dim j As Integer
  • Dim i406adapter As Integer
  • If model406flg Then
  • i406adapter 1
  • Else
  • i406adapter 0
  • End If
  • i initio(addmod, Address)
  • j setb32flgi(i406adapter) ' constant set
    1 or 0 after bit3.dll declarations above
  • VB_InitIOi i
  • End Function
  • Function VB_getlasterrs() As String
  • Dim s As String 255
  • Dim iworked As Integer ' this is more of
    J.W's trick
  • s String(255, 0)
  • iworked getlasterrps(ByVal s) ' this is
    the final part of J.W.'s trick

24
Why Wrap Functions?
  • Initially it made things more robust. (Fewer blue
    screens of death when a c routine was passed the
    wrong type in an argument.) Allows VB(A) to
    better trap common programmer type (checking)
    errors b4 making the c call.
  • Can hide any tricks being used to call into the c
    code. (Strings are a bit tricky/weird/magic.)
    Keeps all the tricks in one place to prevent
    argument calling errors and thus aide robustness
    as above.
  • However the best reason here is that it allows
    one to change Libraries (DLLs) easily. Due to
    differences in price and capability and
    historical reasons, various test stand use
    different Bit3 models and even busses. By
    wrapping whatever DLL is called in its own
    module one may isolate and minimize any
    differences to the rest of the Worksheet. Thus a
    whole worksheet developed on one test stand may
    be run on a completely different test stand by
    changing out the Bit3 module. A worksheet that
    is moved this way can be changed to run on a
    different operating system (different ways of
    getting to the hardware drivers) and/or use a
    different Bit3 model (different busses!) in 5
    minutes by cutting and pasting in different VBA
    modules. (Note the similarity to a language
    called modula which was a successor to
    Pascal.) This module feature has been
    extremely useful for us. Specific Bit3 DLL and
    modules info available at http//d0server1.fnal.
    gov/users/angstadt/www/d0notes/2589/convertb3.htm.
    In general modules are a good thing (precursor
    of objects) and should be used if and where ever
    possible. In most cases the cost is at most a
    microsecond or 2 at run time depending on the
    hardware one is running on.
  • Modules are also a way of dividing and
    conquering. If two people are working on the
    same sheet one could make their changes in one
    module and the 2nd in another. Periodically the
    new modules could be replace or updated and then
    checked to make sure they worked as intended
    together. If so then it could be released.
    Then the next round of changes would be made and
    the process repeated until the Workbook was
    done. This is good practice. If you take an
    existing Worksheet over and start to modify it
    then if possible please add new code
    modifications (your) own new module(s). That way
    if fixes/improvements/patches are made to the old
    ones in your sheet are developed by someone else
    the old modules can be easily changed and/or
    upgraded as necessary. This is easy to do as
    long as your changes are not mixed in with
    theirs. Then its all yours and you have to fix
    everything yourself! Modules can be a very good
    thing!

25
Typical Bit3 Calling Sequence
  • It is assumed InitVME() is called outside of and
    sometime before a VME access (reading or writing)
    to the VME bus. Once it is called it should not
    have to be called again unless any of the
    following occurs
  • Power is removed from the crate and turned back
    on.
  • VBA execution is halted via the Esc key or
    Ctrl-Brk. (Best to do this but may not be
    required)
  • If for some reason a piece of code is run where a
    lot of invalid VME addresses occur. After a lot
    of no DTACK ing the Bit3 may be need to be
    reinitialized before valid addresses start
    working again. (After a big bunch something
    latches in the Bit3 that the quicker error
    clearing mechanisms dont clear it. A total
    global restart is the only thing that brings it
    back but this nominally takes a second so it is
    not done automatically all the time in the
    driver. It usually takes seconds of invalid
    addresses before the Bit3 really latches like
    this. (On a fast machine in tight code this
    could theoretically be gt300 to 400K times.)
    See next major section for more.
  • Any time a valid VME address is put on the bus
    and a VME modules DTACK LED does not light.
    (Occurs rarely but it can happen. Reseating
    cards in the busses and/or cables may be the fix.
    Check VME crate power. Pull all VME modules but
    the arbitrator, Bit3 and target to check if of
    them has latched bus grant or some other VME bus
    signal. Check that all jumpers are correct on
    all boards. If not a VIPA crate and if the VME
    Bit3 card is not jumpered for Bus Arbitrator and
    not in slot 1 then Bus Grant 3 may not be making
    it to the VME Bit3 card. (The 1553 card does not
    jumper bus grant 3 across for example. (Crate
    configuration and jumpers may need to be
    changed.)
  • After calling InitVME() one should wait at least
    a second (and perhaps 2) to be safe. (The latest
    2nd version for NT has a half second delay in
    it at the end of it (already) for the precision
    timing calibration it uses.) All of the Bit3
    driver DLLs keep a (latch on a Bit3 detected
    error) global flag in them, iabortflg. It is
    reset (false) only at power up and only whenever
    VB_clrlatcherri() is called. VB_islatcherri()
    always returns 0. VB_islatcherri() value is in
    re-setting the flag without going through the
    whole init Bit3 process and not in what it
    returns. This flag, iabortflg gets set True ( ltgt
    0) for any detected Bit3 VME failures. It
    latches in this state until reset via a call to
    InitVME() or VB_clrlatcherri() is called. (Thus
    any granularity of error checking is achieved.)

26
Typical Bit3 Calling Sequence 2
  • VB_getlasterrs() returns a string that indicate
    what the Bit3 and driver thought the last VME
    error detected was. Possible values are " VME
    TIMEOUT, " VME BUS ERROR, " VME PARITY
    ERR, " DMA ERROR, "connect giveio.sys
    failed , connect mapmem.sys failed , "no
    vme access no buff from mapmem.sys . Any and
    all combinations of the first 3 may be seen
    together on a VME access and mean that for some
    reason NO DTACK came back for that address.
    The latter errors may occur only in the NT
    version of drivers and indicate that something is
    not working between the driver DLL and one of the
    drivers (.sys binaries) it is using. They may
    not be running for some reason and/or installed.
    If "no vme access no buff from mapmem.sys
    occurs it means something pretty bad happened in
    mapmem.sys and/or its connection was broken.
    Saving any unsaved work if desired and leave
    Excel entirely and come back into it. This seems
    to mostly happen when stopping VBA code execution
    via Ctrl-Break (during VBA development.) I
    apologize for not being able to totally make
    this go away entirely. Although it is an
    annoying nuisance it has not been a show stopper.
    Recently Ive found that not putting
    VB_InitIOs() in any of the cells seems to delay
    the onset of this considerably. More on this
    later in How Excel Recalculates determinism
    (or lack of it.) ... Most VME errors are
    trapped but there are a few conditions that may
    not be. These rare and usually due to a botched
    driver install for some reason or other. Best is
    to call me if you are having troubles so I can
    come and look.
  • Read routines have no error status back and one
    must use the above mechanisms for error checking.
    They just return the value they read. (This
    allows the function to be placed directly in an
    Excel cell!) Write routines return 0 on detected
    failure and a 1 on success. There is enough
    their so that one could re-write the wrappers to
    give back any kind of calling interface that
    could be imagined/desired.)
  • If using getvmedmal() (only available for the 6xx
    models) then it returns its own error code in
    addition to the first mechanism described above.
    On return this must be checked after every DMA
    for a 1truedata is valid. The user buffer is
    not zeroed in the interest of speed. (The caller
    may 0 some or all of their buffer before doing
    the DMA if they desire.) Other error codes are
    from bntdv617.h
  • after the dma is complete the data will be
    copied to this buffer and
  • // the routine will return success1 or
    failure false0 or -99 if
  • // it could not create a 64K special dma
    buffer. if the return is -99
  • // close the program (unload the dll) and then
    reload it.

27
Example of a Typical Bit3 Calling Sequence after
a call to VB_InitIOs() or VB_InitIOi() (and crate
not power cycled.)
  • Sub go53mhzOsc()
  • Dim lAdd As Long
  • Dim iIs1EqualTrueIfSuccessElse0EqualFalse As
    Integer
  • Dim iPlace As Integer
  • iPlace VB_clrlatcherri ' clear the
    latching bit3 status error flg (iplace should
    always 0 !)
  • lAdd lVRBCBASEADD 32782 H800E 'vba
    sign extension bug bites...
  • iIs1EqualTrueIfSuccessElse0EqualFalse
    VB_Writew(lAdd, 0) ' select normal operation
    for autotest fpga
  • If VB_islatcherri 0 Then
  • 'MsgBox "no errors detected processing list
    in sub ListProc may not honor empty block if!
  • Else
  • MsgBox "one or more NODTACK during
    go53mhzosc"
  • End If
  • ' Go to IDLE NRZ in order for the Sequencer to
    establish the framing bit
  • ' Call goIDLEnrz

28
A Word on Notation
  • In the code fragments presented so far you may
    have noticed odd things like an l (lower case
    L) in front of lAdd (Add is short for address
    in this case a VME physical address.) l is
    short for long. In iPlace the i is short for
    integer. sz indicates a string with a zero
    terminating it (basically a C type of string as
    opposed to a VB string which probably will not
    have a 0 terminating it.) b is for Boolean.
    mod is short for module. txt is short for a
    text box. It must be stressed that this is a
    convention only. What really determines what
    type of the variable is the Dim statement
    wherever it is declared. Thus Dim iVal as
    Long fails to follow the convention and is
    misleading i implies a 16 bit integer but it
    is in reality a 32 bit Long.
  • This is a form of Hungarian Notation (plenty
    under Google for this string!) originally
    described by Charles Simonyi, a Hungarian with
    an unpronounceable last name, hence it became
    known as Hungarian notation. Originally this was
    for c code. G Reddick and Lesznynski expanded
    it to be the Reddick VBA or RVBA naming
    convention. One of the things Simonyi argued
    pretty strongly (about if I remember correctly)
    was to put the type up front followed by a
    capital letter signifiying when the type ends and
    when the variable name starts as opposed to
    having it at the end which was previously more
    common before Simonyis writings.
  • Naturally a lot of my C DLL code base is from
    code written before I knew of Hungarian or RVBA
    notations. It was based on suffix indicators
    such as flg for a flag, w, for (unsigned) word,
    i for integer, ect. After RVBA I begin using a
    mixture! Thus in the c variable iAbortflg the
    i is for (short 16 bit) integer (used as) a
    flg. I avoided a Boolean type because I wasnt
    sure if VB and C would use the same number of
    bits.
  • For VB I think Hungarian notation is useful
    because an integer in VB has always been 16 bits
    and a Long has always been 32 bits from the 16
    bit version 4 (Office XP is 10 now.) 8 years
    ago. For C where the code iVal int can change
    from 16 bits to 32 bits or vice-versa with a
    different platform and/or compiler! (or perhaps
    even 64 with a third platform!) So old C code on
    ports like this could require tons of editing to
    fix completely misleading notations. If its a
    large quantity of lines then probably no one is
    going to go and change all the names because of
    the high probability of introducing too many
    mistakes. Any notation is just meant to be an
    aide to quick understanding of code. If it does
    not succeed at that then it might not be worth
    the extra work.

29
A Word on Notation (2)
  • Why so important? Were doing mixed language
    programming so the arguments and return values
    must match or a possible blue screen of death
    could result. We have to pay attention to our
    calling arguments and make them match the
    declarations in the Bit3 module. A word or two
    about the code may help you decipher it if you
    feel the need to have to look at it!
  • Back to trying to clarify what youre looking at.
    Heres the C code for the islatcherri()
    function
  • DLLEXPORT __int16 WINAPI islatcherri(void)
  • return (short) iabortflg
  • Another example is getlasterrps the p
    is short for pointer and s is short for string.
    So the whole thing spelled out is Get the last
    error returning a pointer to a string.
  • So for a lot of the Bit3 functions I used use my
    old suffix notation on the type of VME operation
    they will put on the bus and/or return 8, 16 or
    32 bits. It sort of works i for signed 16
    bits, b for byte8. Very nice!
  • For a model 6xx that support 32 bit operations
    then the wrapped VB_readl(), VB_writel() and
    VB_readul() are provided that wrap the DLL
    readvmeul() and putvmeli() actual DLL entry
    point.
  • Note that in all Bit3 functions is a
    misleading/confusing name ending writevmeli()
    Another reason to just use the wrapped
    functions. Here the conventions break down. I
    apologize for this. WriteVMEli() exported
    function available which the header file tries to
    clarify
  • DLLEXPORT __int16 WINAPI writevmeli(long
    pdaddress,long lval)
  • / this name and the second argument of
    writevmeli are misleading.
  • writevmeli does NOT do a 32 bit word vme bus
    cycle.
  • it does only a 16 bit vme bus cycle. the
    argument is 32 bits to
  • facilitate getting back a 16 bit unsigned
    quantity short to Visual Basic
  • as VB has no short intrinsic unsigned
    (__int16) __int16. in no way shape or form
  • does this do a 32 bits to vme.
  • A long is necessary to hold an unsigned 16
    bit quantity. (More on next section.)
  • (The models 6xx can do 32 bit VME operations and
    there are a few additional calls for those
    libraries. It is easy to move up to a 32 bit
    model by cutting and pasting in new VBA code but
    going down is only easy if 32 bit VME operations
    are not needed/used in the rest of the sheet.)

30
A Word on Notation (3)
  • In one early sheet I found 2 possible wrappings
    of WriteVMEli which I thought might be
    interesting because the wrapper adds
    functionality to return the last error string
    instead of a 0 or 1 (failure, success
    respectively). If you need a slightly different
    style then there is enough here I think to morph
    the arguments and return values to your needs!
    This is from a module called io_32 in hv5_32.xls.
    Its for a 40x under Win 9x, Bit3_32.Dll but
    it would work the same under the equivalent NT
    DLL, BNTDV40X.dll.
  • Function VB_Writew(Address As Long, lvalue As
    Long) As Integer
  • Dim i As Integer
  • i WriteVMEli(Address, lvalue)
  • VB_Writew i
  • End Function
  • Function VB_Writews(Address As Long, lvalue As
    Long) As String
  • Dim i As Integer
  • Dim s As String 255 s is declared here
    with space (a buffer) for 255 characters
  • i WriteVMEli(Address, lvalue)
  • s String(255, 0) ' every character of
    the string is now set to 0!
  • s VB_getlasterrs() ' this returns the
    last error string from the bit3 C driver
  • VB_Writews s
  • End Function
  • So this notation is to try to indicate that
    VB_writew() writes an unsigned word (returning
    the usual and/or default integer 0,1 as a 16 bit
    integer) while VB_Writews() writes an unsigned
    word returning a string indicating an error or
    ok! if no error was detected. Both do this by
    wrapping the unsigned 16 bit word into a larger
    signed 32 bit word or long. Why do we have to
    package up an unsigned 16 bit quantity in a
    (signed) long of 32 bits?

31
Some Problems with VBA and Some Work Arounds
  • Unfortunately VB(A) has no intrinsic unsigned
    types. Everything is signed. An integer is
    always 16 bits (0xffff) -32768 to 32767
    (0x7fff) in VB(A) though other languages
    (usually) provide a 16 bit unsigned integer 0 to
    65535 (0xffff)
  • Long is also signed (0xffffffff)-2,147,483,648 to
    2,147,483,647 (0x7fffffff)
  • Unsigned Long would be 0 to 4,294,967,295
    0xffffffff)
  • Note something helpful to remember is that for
    any signed quantity the largest positive value it
    will hold is 0x7f in the high byte (on a 2s
    compliment machine, which most computers are
    including Wintel).
  • Assigning h8000 to a long doesnt work! One
    gets 0xffff8000 and not 0x8000. (sign extension
    problem on any hex value gt 0x7fff. This has been
    a real pain!
  • Workarounds
  • Promote everything to more Bits. Use a long to
    hold 16 bits being careful to use decimal instead
    of hex for values gt 0x7fff.
  • Pass it onto the C stack where the C argument is
    unsigned and/or larger (more bits) as above.
    E.g., if you need 0 to 65535 then use a long. If
    gt 2 billion then use a double. Etc. (can use
    arbitrary long integers with C and inline
    assembly. I have an example of using gt 64 bits
    using the ADDC instruction using double and 2
    longs so that modulo operations still work on the
    lower 32 bits.
  • Use strings! Can also pass it as a hex string and
    convert it to binary where necessary.
  • VB(A) doesnt do true bit shifting some fixes
    available in xutil.c and more elsewhere.
  • Conclusion/Summary Due to its extensibility
    many/most limitations can be worked around. (One
    that cant be is the programmers lack of
    imagination and/or skill!)

32
Concept of Lists
  • B4 objects there was structured programming
    with a fundamental tenet being that one function
    (and/or subroutine) did one thing (in as
    generalized a way as possible) (Just as there
    are objects now) One can expand this to the
    concept of a list.
  • Make One list do one thing. Maybe you have a
    list for the first grocery store and a 2nd list
    for another due to a sale at the second but the
    first has better produce. Maybe another for the
    Hardware store, etc. Maybe after all your lists
    are made and organized you expedite them by
    shopping. The idea is the same, make a list of
    like VME read/writes, their addresses and values,
    and then expedite or execute that list! (Make
    the VME DTACK LEDs light!)
  • (FYI There are languages built around this list
    concept including a now somewhat obsolete
    language called Lisp which I think now is quite
    dead due to its difficult to use of parenthesis
    on top of parenthesis. It wasnt pretty but it
    had power for those that could keep track of and
    parse the parenthesis.)
  • Remember one of our first goals was to reduce the
    number of lines of code? One way is the concept
    of a list processor. Not new, many programs
    (had) have file based list processors of various
    sorts. The next slide is a simple 48 line VBA
    subroutine based on the Bit3 module that will
    process a VME list.

33
A (simple) VBA VME List Processor (48 lines)
  • Sub ListProc()
  • Dim iRow As Integer
  • Dim iMax As Integer
  • Dim iplace As Integer
  • Dim lAdd As Long
  • Dim lVal As Long
  • Dim iVal As Integer
  • Dim iAddMod As Integer
  • Const iROWSTART As Integer 16
  • Call allAutoOff
  • iplace VB_clrlatcherri ' clear the
    latching bit3 status error flg
  • iRow iROWSTART - 3
  • iMax Cells(iRow, 4).Value
  • iMax iMax iROWSTART - 1
  • For iRow iROWSTART To iMax
  • lAdd Cells(iRow, 4).Value
  • iAddMod Cells(iRow, 11).Value
  • If iAddMod ltgt 0 Then ' if not 0 then send a
    new add mod
  • iplace VB_setaddmoda(iAddMod)

34
List of Lists (of Lists!)
  • If a Workbook had several Worksheets in it with
    each worksheet having one list then they could be
    chained together for the cost of 2 lines of VBA
    code per link. The following is a somewhat
    artificial example to try to make things clearer
  • sub doAList
  • Sheets(InitBoard1").Select
  • call ListProc
  • Sheets(InitBoard2).select
  • call ListProc
  • Sheets(DoSomething1).select
  • call ListProc
  • ..
  • until all of the sheets are exhausted
  • could make branching statements using if and
    case based on values coming back in certain
    cells.
  • could also do one list multiple times ect.
  • Can call other sheets and load them
  • Workbooks.Open FileName
    "C\xls\xls_CTS\\List617_2.xls"
  • Sheets(Sheet VME1).select
  • call ListProc

35
List of Lists (of Lists!) 2
  • Any list processor can be made Quiet, Silent,
    or Invisible with Application.ScreenupdatingFals
    e (It will also run faster!)
  • Just Remember to turn it on with
    Application.ScreenupdatingTrue when you are
    done! Else the worksheet will no longer paint the
    screen again until it is reopened! (Not widely
    used but it is available.)
  • A few sheets have a quiet or deferred error
    handler. So they are quiet and dont check for
    errors until all the lists have been completed.
    Not widely used but is available and/or could be
    done if desired.
  • List Processing Concept is very powerful. Saves
    lots of programming time at some expense to run
    time (only on slow machines!) Most widely used
    with 1553 and Sequencer test where even a
    pass/fail test was developed with it using a
    procedural write- up. This technique has the
    advantage of the same code and Worksheets being
    used for debugging by the engineer and/or skilled
    technician. Engineer made up most of the lists.
    Took very little additional programmer time. No
    time wasted on dead code because all code (and
    Worksheets) is still in use (whenever a sequencer
    does need repairing)!

36
Types or Purpose of WorkSheets in Use
  • What sheets do we have done that can be looked
    at? (for examples, lifting/reusing code ect.)
    Tons! (Megabytes! gt 5 Person years!) So many I
    am out of quota on the servers so if you dont
    see it there ask me! All kinds including but not
    limited to (and in no particular order)
  • Small 1 Crate DAQs (both SASEQ and VRB,VRBC
    based) for both Silicon chips and AFE boards.
    (Way different sheets.)
  • FPGA reprograming A sheet for reprogramming
    VRBs (downloads new firmware to battery backed
    RAM that it will boot from.) Also a VRBC
    download worksheet. These last two use the Bit3
    to load new Altera programs to the FPGAs on the
    board via VME Bit3. (Jamieson uses the
    parallel port as an interface to his boards as
    they are not VME based. He as also done some
    JTAG testing using the parallel port as his
    hardware is not VME based.)
  • Front Panel control and display substitue A High
    Voltage Front Panel Display and Control Sheet(s).
  • Front Panel control and display of the DZero
    clock and statistical testing. (run for
    months/years? In Feynman on a Win 9x box!.
  • General Engineering Control and Exercising VME,
    CAMAC, 1553 List Processors for all of the
    above and more including the DZero Clock (in
    Feynman), and Mike Utes Sequencer(s).
  • Confirming VRB VRBC operation and
    troubleshooting including engineering,
    Statistical (and/or FPGA emulation!) functions.
    Most recent sheet with many modules in it. Still
    under development for CTS. (A work in progress.)
    But a version allowed Ted Zmuda to come up with
    VLPC firmware that ran the VRB 1 VRBC gt 9.1
    billion times without failure. (It used VME
    (Block Transfer DMA! my Bit3 driver!) at L1
    rate gt 20Khz and L3 rate of 6 Kilohertz on
    Lyns 2Gig machine (thanks Lyn!). Used Bit3 and
    Parallel port for trigger and handshaking. Kept
    track of everything and provided support for
    triggering Teds Logic Analizer via the parallel
    port. (A 24 bit (16Mega) wrapping problem could
    be exercised and looked at quicker on the logic
    analyzer then it could be simulated by the Altera
    software.) So it could trap errors and trigger
    things as well as do statistics. (9.1 billion
    events takes 18 days. 0 errors. Way to go T.
    Zmuda!)
  • 1553 Spy (Logic analyzer) Worksheet on a Laptop
    (Shouas.) Uses the Ballard driver for their 1553
    PCMCIA card. Some versions have the ability to
    trigger a scope via the Parallel Port!
  • AFE characterization M. Matulik, P. Rubinov.
  • Pass/Fail Production Testing (M. Matulik. and J.
    Anderson)

37
Random Hints, (words to the wise).
  • Dont use spaces in object and/or sheet names.
    (If nothing else it may be hard to distinguish
    between a space and a _ due to some line on the
    lower margin.) It almost works but sometimes..
    Just dont!
  • VB is not case sensitive (it echoes case for
    clarity after you declare it.) except in side of
    quotes Sheet 1 is not the same as sheet 1
  • When is VB not block structured? When the first
    block of the if is commented out! May have to
    change the sense of the if. (This recently
    burned me!)
  • Best to be explicit in the if statement avoid C
    usage of If. E.g. if (myVar) then may not
    work. Best is to use if (myVargt0) or if
    (myVarTrue) or if myVarFalse) which leads us
    to the next thing.
  • Spell things out sequentially. In general dont
    stack things up in (). Make a variable and
    feed that to the next routine and/or set of ().
    Allows type checking and since it gives the
    parser less grief it gives you fewer gray hairs
    as well.
  • For speed use With, End with blocks when
    dealing with many instances of the same daughter
    object. Supposedly it saves re-verification that
    the parent object exists. (Unfortunately withs
    do not nest.)

38
A Word About Arguments (and Pointers)
  • Although VB VBA does not EXPLICITLY support
    pointers the default argument passing is by
    Reference (or basically a pointer!) This is as
    opposed to by copy. FORTRANs default is also
    by reference as opposed to Cs default of by
    copy. (C also support passing things by
    reference as well when a functions argument
    declaration(s) include the use of a pointer
    ((address) dereferencing operator) .
  • When passing arrays back and forth between C and
    VB(A) one should be aware that C starts all
    arrays at 0. The default for VB(A) is also 0.
    However in VB(A) it can be changed via either
    Option base 0 or Option base 1 at the top of
    a module. When passing arrays back and forth
    between C and VB(A) I think it very wise to
    explicitly put Option Base 0 at the top of the
    module. One less point of confusion for the
    interpreter and for the author/reader/programmer.
    It just keeps everyone on the same page.
  • Generally, when matching arguments to C code in a
    DLL if it is not declared as a pointer (no )
    then it typically needs the VB byval qualifier
    which tells VB it is passed as a copy. (Usually)
    Look in the .h file to see how to call it or
    other documentation (book or whatever.). (An
    exception is passing strings. For now just
    pretend it is in the realm of magic. But if
    you insist there is an example in the Bit3
    library with VB_getlasterrs() with comments and a
    reference.
  • There is a newer dialect of VB out called NET
    VB which Im not talking about here. Of course
    you know its default is the opposite of VB(A)
    and we are in no way referring to that! This was
    for a Web scripting environment as a Java
    competitor. At the moment we are just working
    locally so we are less concerned about security
    and/or protection which is why they bit the
    bullet and changed it all around! (VB and VBA
    were built to be extended!)
  • Probably the most important thing to realize is
    that passing a variable by reference into say a
    subroutine is that if that sub you passed it into
    changes it, then its changed in the callers
    variable as well. This is good for passing
    arrays as in FORTRAN and C. However when
    overlooked it is the fas
Write a Comment
User Comments (0)
About PowerShow.com