VB How To:

Well....I know how to make plain text. ASCII text. And .ini file format.

I use it for all different things.

I even created my own file format for a word processor.

It's really easy to write text files.

Essentially you create the file, and then print text to in line by line. Or you can print entire controls or variables. This can be used as a saved game if you structure it right.

Here is an example I use:

Open "C:\test.txt" For Output As #1
Print #1, "Hello"
Print #1, "This is my new text file"
Print #1, text1 'this prints the contents of a text box to the file
Print #1, 'Empty Line
Close #1 ' This closes the file (must be done to save memory.
 
Following on from Corn's info on how to print to a text file, I decided to post how to read from / write to an .ini file.

.ini files were what early versions of windows and other software programs used instead of the registry that many use now. They are still quite useful for data storage on a small-scale.

An .ini file is made up of sections and keys. Each section is indicated via a square bracket around it, and each key is listed under these section headings, in the format "keyname=keyvalue".

Here is an example of what one may look like (it is stored as plain text):

Code:
;
;Note to user: DO NOT ALTER OR DELETE THIS FILE.
;
[SMS Inventory Identification]
Version=1.0

[Product Specification]
Product=Windows 2000 Professional

Version=5.0
Localization=English
ServicePackNumber=0
BitVersion=40 
[Version]
DriverVer=11/14/1999,5.00.2183.1

There are various windows functions that can be used for maintenance of these files. You can read in individual values or entire sections, and write values or sections.

The following code is used to read a value from a given key in a given section of a given .ini file:

Code:
[color=blue]Private Declare Function[/color] GetPrivateProfileString _
   [color=blue]Lib[/color] "kernel32" [color=blue]Alias[/color] "GetPrivateProfileStringA" _
  ([color=blue]ByVal[/color] lpSectionName [color=blue]As String[/color] , _
   [color=blue]ByVal[/color] lpKeyName [color=blue]As Any[/color] , _
   [color=blue]ByVal[/color] lpDefault [color=blue]As String[/color] , _
   [color=blue]ByVal[/color] lpReturnedString [color=blue]As String[/color] , _
   [color=blue]ByVal[/color] nSize [color=blue]As Long[/color] , _
   [color=blue]ByVal[/color] lpFileName [color=blue]As String[/color] ) 
[color=blue]As Long


Public Function[/color] GetKey(SectionName [color=blue]As String[/color], KeyName [color=blue]As String[/color], _
                                Inifile [color=blue]As String[/color]) [color=blue]As String[/color]

[color=green]'Retrieves a value from an ini file corresponding
'to the section and key name passed.[/color]
        
   [color=blue]Dim[/color] Success [color=blue]As Long
   Dim[/color] nSize [color=blue]As Long
   Dim[/color] ret [color=blue]As String
  
    Dim[/color] Defaultvalue [color=blue]As String[/color]
    Defaultvalue = "Not Found"
  
  [color=green]'call the API with the parameters passed.
  'The return value is the length of the string
  'in ret, including the terminating null. If a
  'default value was passed, and the section or
  'key name are not in the file, that value is
  'returned. If no default value was passed (""),
  'then success will = 0 if not found.

  'Pad a string large enough to hold the data.[/color]
   ret = Space$(2048)
   nSize = Len(ret)
   Success = GetPrivateProfileString(SectionName, KeyName, _
                                     Defaultvalue, ret, nSize, Inifile)
   
   [color=blue]If[/color] Success [color=blue]Then[/color]
      GetKey = Left$(ret, Success)
   [color=blue]End If
   
End Function[/color]



To write a new value to the file, use the following:


Code:
[color=blue]Private Declare Function[/color] WritePrivateProfileString _
   [color=blue]Lib[/color] "kernel32" [color=blue]Alias[/color] "WritePrivateProfileStringA" _
  ([color=blue]ByVal[/color] lpSectionName [color=blue]As String[/color], _
   [color=blue]ByVal[/color] lpKeyName [color=blue]As Any[/color], _
   [color=blue]ByVal[/color] lpString [color=blue]As Any[/color], _
   [color=blue]ByVal[/color] lpFileName [color=blue]As String[/color]) [color=blue]As Long[/color]


[color=blue]Function[/color] WriteKey(SectionName [color=blue]As String[/color], KeyName [color=blue]As String[/color],  _
NewValue [color=blue]As String[/color], Inifile [color=blue]As String[/color])
[color=blue]Dim[/color] Success [color=blue]As Long[/color]
Success = WritePrivateProfileString(SectionName, KeyName, NewValue, Inifile)
WriteKey = Success
[color=blue]End Function[/color]


Another useful function is the one to delete an entire section:

Code:
[color=blue]Function[/color] DeleteSection(SectionName [color=blue]As String[/color], Inifile [color=blue]As String[/color])
    WritePrivateProfileString SectionName, _
        vbNullString, vbNullString, Inifile
[color=blue]End Function[/color]

You can modify the functions to give a return value to let you know if the operation was a success or not.
 
Hi, can anyone tell me how to build a webpage with Visual Basic (such as with DHTML or any other means ?) My problem is, whenever I build a webpage (ex with DHTML,) it will always create a supporting .dll or .ocx or .exe (a supporting exe not a really executable file, you still run it from the HTML document) Free websites do not support dll's etc. Also you will need to tell the person that owns the server to actually activate the .dll in its new location (by typing regsvr32 documentname.dll)

Thanks in advance
 
Originally posted by apiaster
Hi, can anyone tell me how to build a webpage with Visual Basic (such as with DHTML or any other means ?) My problem is, whenever I build a webpage (ex with DHTML,) it will always create a supporting .dll or .ocx or .exe (a supporting exe not a really executable file, you still run it from the HTML document) Free websites do not support dll's etc. Also you will need to tell the person that owns the server to actually activate the .dll in its new location (by typing regsvr32 documentname.dll)

Thanks in advance

To be honest, I've never created a web-page. However, you can write a webpage in normal HTML that supports VBscript (instead of using Java as the scripting language). This may limit you to what web-browers can 'read' the page - I'm not sure if the latest netscape or the likes of opera support vbscript.

I've seen some examples of vbscript, and it is very similar to VB, so the learning curve may not be great.

I don't know whether this requires "support" files though.

Do a seach on google or similar for vbscript tutorial.

Here is an example tutorial, and you can see that the concepts are pretty easy. :)
 
I am making a form and have run into some problems.

There are several rows in the form, and the user has the possibility to add rows if he wants to (with a macro). Some rows have combo boxes or check boxes in them, and problems occur when these are copied. All contents and formatting works ok, but the new control boxes are exact copies of the original controls. That is, if you copy the formula C2+D2 one row down it will change to C3+D3, but the combo box will still have the SAME cell references as the original combo box. :mad:

So what I´m asking is how to make the new control unique (I guess the new control should be given a new name, now it's name is the same as the original) and how to make its cell references to point one row down from the original's?

Thanks in advance for any help. :)
 
Cornmaster asked, How can I make two web browser controls "mirror" each other. This means that when you go somewhere in one....it automatically displays it in the other too.

Try using Javascript. There is probably an onChange event that you could use to run a little script... In JavaScript, beware of your capitaliZation! You could perhaps just as easily use VBScript.

apiaster asked about building a dynamic webpage. I agree, dll's are a pain. Lots of hosts have enabled the .asp suffix. Try uploading your htm file, same thing exactly, as an .asp file (test.htm = test.asp). If it runs from a browser, you've got an asp interpreter!

The detailed answer to both of these questions can probably be found on Google. Whenever I need some new code, that I can't cut/paste from stuff I've already done, I just search Google.
Typical search: +asp +date +format
Or even cut/paste the error message! The amount of detailed solutions and examples out there is simply amazing!

Welcome to the Next Generation.
 
Originally posted by ainwood
Is this in VB or VBA?

Maybe if you post your code it would help. :)

VBA.

The problem is of course that I don´t have any code. :o I´m not very familiar with programming controls in VBA, so after having tried without success for a few hours, I decided to bypass the entire problem by removing the combo boxes totally.

My very simple solution now is to instead have a number of rows hidden from the start, and let the user make them visible by clicking on a button. This is the code:

Code:
Private Sub ButtonChecker()

Dim RowNumber As Integer
    
      Select Case Application.Caller
      
            Case "button 1"
            
                RowNumber = 31
                
                Do While Rows(RowNumber).EntireRow.Hidden = False
                RowNumber = RowNumber + 1
                Loop
                
                If RowNumber >= 41 Then
                MsgBox ("Only 10 rows available")
                Else
                ActiveSheet.Unprotect
                Rows(RowNumber).EntireRow.Hidden = False
                ActiveSheet.Protect
                End If
                
               Case "button 2"

               ' And so on...

I.e. the macro puts the cursor at that button's first hidden row, and then unhides one. If all rows already are visible, a message box pops up.
 
Well, good that you got it working! :)

Yes, Excel does strange things with embedded controls. You will find that any "new" controls are given a new name with a sequential number on the end - you could actually use the new name to change any cell references etc. You could detect the new one by creating a collection of the old ones, and enumerating all the controls to identify the new one when its created.

BTW - it looks like you used controls from the "forms" toolbar, rather than the "control toolbox" toolbar. They are actually slightly different - the "Control Toolbox" ones are better to use with VBA, whereas the forms ones are easier to use if you don't want to have to write macros. :)
 
Originally posted by ainwood
Well, good that you got it working! :)

Yes, Excel does strange things with embedded controls. You will find that any "new" controls are given a new name with a sequential number on the end - you could actually use the new name to change any cell references etc. You could detect the new one by creating a collection of the old ones, and enumerating all the controls to identify the new one when its created.

BTW - it looks like you used controls from the "forms" toolbar, rather than the "control toolbox" toolbar. They are actually slightly different - the "Control Toolbox" ones are better to use with VBA, whereas the forms ones are easier to use if you don't want to have to write macros. :)

Any good tutorials on how to use the "control toolbox" controls out there?
 
Do a search on google or other for some. I found one here.

If you have any problems, just let me know. I learnt just by reading other peoples' source code, and trying to learn what code does what action.

If you have any specific examples of what you want to do with excel (for example), then let me know and I can probably write you some code that you can study. :)
 
Thanks. That's how I have learned VB, too. Bump into some problem, search for other peoples solutions to similar problems and adapt it to your own problem. :)
 
Here are a couple of basic functions for converting Longs to Hexadecimal and vice-versa. May be useful if you want to write utility editors etc ;)

Code:
[color=blue]Function[/color] LongToHex(lngLong [color=blue]as Long[/color]) [color=blue]as string[/color]
    LongToHex = Hex$(lngLong)
[color=blue]End Function


Function[/color] HexToLong(strHex [color=blue]As String[/color]) [color=blue]as Long[/color]
    HexToLong = [color=blue]CLng[/color]("&H" & strHex)
[color=blue]End Function[/color]
 
Along a similar line, if you want to work with singles and doubles, it is a bit more difficult. The "easiest" way to convert "Hex" into a single etc, may actually be to just read the binary data into a variable.

For example, a "single" data type occupies 4 bytes. If you therefore read 4 bytes of data from a binary file into a variable declared as a "single", then the "conversion" has already happened.

Eg:

Code:
[Color=green]'Write a "single" value to a binary file.[/color]
[color=blue]Sub[/color] WriteIt()
[color=blue]Dim[/color] i [color=blue]As Long[/color]
i = FreeFile

[color=blue]Dim[/color] sglPI [color=blue]As Single[/color]
sglPI = 3.141592

[color=blue]Open[/color] "C:\apps\hex.bin" [color=blue]For Binary As[/color] i
    [color=blue]Put[/color] i, , sglPI
    [color=blue]Put[/color]  i, , sglPI
[color=blue]Close[/color] i

[color=blue]End Sub[/color]

The above code simply writes two single variable to a data file. Open it with a Hex Write a "single" value to a binary file. If you now open the file with a Hex Editor, you will see that the Hex is:

D8 0F 49 40 D8 0F 49 40

Now, you want to read this back in. To illustrate the point a bit better, I will give the code to read in the second value. To do this, you just use the "Get" function, and tell it which byte to start reading from:

Code:
[Color=green]'Read a "single" value from a binary file.[/color]
[color=blue]Sub[/color] ReadIt()
[color=blue]Dim[/color] i [color=blue]As Long[/color]
i = FreeFile

[color=blue]Dim[/color] sglPI [color=blue]As Single[/color]

[color=blue]Open[/color] "C:\apps\hex.bin" [color=blue]For Binary As[/color] i
    [color=blue]Get[/color] i, 5, sglPI
[color=blue]Close[/color] i
[color=blue]Debug.Print[/color] sglPi

[color=blue]End Sub[/color]


If you want to convert it the "harder" way (ie - convert a hex "string", you need to use a clever trick. You can't just use the CSng() function. Instead, you have to read the Hex into a Byte array, and then "copy" that memory onto a single variable type. This is done with user-defined types, so that the LSET function can be used.

Code:
[color=blue]Private Type[/color] DummySingle
    Output [color=blue]As Single
End Type[/color]

[color=blue]Private Type[/color] HexBytes
    TheBytes(0 [color=blue]To[/color] 3) [color=blue]As Byte
End Type[/color]

[color=blue]Function[/color] HexToSingle(strHex [color=blue]As String[/color]) [color=blue]As Single[/color]
[color=green]'declare a byte array[/color]
[color=blue]Dim bytHex [color=blue]As[/color] HexBytes
[color=blue]Dim[/color] i [color=blue]As Integer[/color]
[color=blue]For[/color] i = 0 [color=blue]To[/color] 3
    bytHex.TheBytes(i) = [color=blue]CByte[/color]("&H" & Mid(strHex, i * 2 + 1, 2))
[color=blue]Next[/color] i

[color=blue]Dim[/color] sngOutput [color=blue]As[/color] DummySingle
[color=blue]LSet[/color] sngOutput = bytHex

HexToSingle = sngOutput.Output
[color=blue]End Function[/color]
 
I'm teaching myself VB a small step at a time and I can't figure out what is wrong with this code. Everything works but the part that is supposed to change the units type. The msgbox doesn't come up and the scalemode type doesn't change. Does anyone know what I'm doing wrong?

Code:
Dim Unit As String
-----------------------------------------------------
Private Sub Command2_Click()
  If Unit = "Units" Then
    MsgBox , "Please choose a units type."
  End If
  If Unit = "Pixels" Then
    Form1.Main.ScaleMode = 3
  End If
  If Unit = "Inches" Then
    Form1.Main.ScaleMode = 5
  End If
  If Unit = "Centimeters" Then
    Form1.Main.ScaleMode = 7
  End If
  If Unit = "Millimeters" Then
    Form1.Main.ScaleMode = 6
  End If
  Form1.Main.Width = Text1.Text
  Form1.Main.Height = Text2.Text
  Form1.Main.Enabled = True
  Form1.Main.Visible = True
  Unload Form2
End Sub
-----------------------------------------------------
Private Sub Command3_Click()
  Unload Form2
End Sub
-----------------------------------------------------
Private Sub Timer1_Timer()
  Unit = Combo1.SelText
  Text1.Text = VScroll1.Value
  Text2.Text = VScroll2.Value
End Sub
 
One way of making your code easier to debug is to ensure that you declare all your variables in a set way. You put "i" as a prefix on integers, "cmd" as a prefix on command buttons, "cmb" as a prefix on a combo box etc.

For a bit more info to help your debugging, what is "unit"?

When you have the line 'if Unit = "Units" then', the compiler automatically looks at the default property for the object of "unit" type. If "unit" is a textbox, then that line is fine. If it is a combobox or something else, it may not work.....

I normally put the object property in even if it is the default property.

Eg. If Unit.Text = "Units" then...

Note that VB is case-sensitive. If the entered text is units rather than Units, it will not run the "true" clause.




Ooops - reading further, I see that "unit" is combo1.seltext.

the .seltext returns or sets the selected text of the control. Basically, all this does is highlight the text, as if you'd run your cursor over it!

When using comboboxes, its much easier to just work with the ListIndex of the control - in your case, this will do away with the need to have all the if statements, and the timers - you probably don't even need to command_button, if you use the _Change event for the combobox:

Code:
[color=blue]Private sub[/color] combo1_change()

[color=blue]Select case[/color] combo1.listindex

[color=blue]case[/color] 0
    [color=green]'it hasn't been changed[/color]
[color=blue]case[/color] 1
     [color=green]'pixels[/color]
    Form1.Main.ScaleMode = 3
[color=blue]case[/color] 2
    [color=green]'Inches[/color]
    Form1.Main.ScaleMode = 5
[color=blue]case[/color] 3
    [color=green]'Centimeters[/color]
    Form1.Main.ScaleMode = 7
[color=blue]case[/color] 4
    [color=green]'Millimeters[/color]
    Form1.Main.ScaleMode = 6
[color=blue]case else
end select[/color]

  Form1.Main.Width = Text1.Text
  Form1.Main.Height = Text2.Text
  Form1.Main.Enabled = True
  Form1.Main.Visible = True
 
King of Camelot,

Another good thing to do besides ainwood's advice is to learn about the debugger. Then you can step through the code and see how the variables change or set breakpoints so you can find out when certain things are actually taking place. Learning the various ways that objects interact with each other will take you a long way toward understanding how to orchestrate the events that occur in your code. ;)
 
Ok, now I have a new question. This time I want to create a macro in MS WORD 97 that each time the document is opened increments a number by 1. This is my try at the code:

Code:
Sub Auto_open()

    Dim orderNum As Integer
    
Selection.GoTo What:=wdGoToBookmark, Name:="myBm"
    orderNum = Val(ActiveDocument.Bookmarks("myBm").Value) + 1
Selection.Delete Unit:=wdCharacter, Count:=1
Selection.InsertAfter orderNum
ActiveDocument.Bookmarks.Add Range:=Selection.Range, _
   Name:="myBm"
   
End Sub

The selection and repacement of the bookmark works, but I only got it working for text. The .Value doesn't apparently work with the bookmarks property. :confused:

The bookmark myBm must of course be created before running the macro.
 
Back
Top Bottom