*** edited Geoff W ***
Ok, I see it on this post
Steve,
>I’m attaching the code
Did you attach the code?
![]() |
Patch reliability is unclear. Unless you have an immediate, pressing need to install a specific patch, don't do it. |
SIGN IN | Not a member? | REGISTER | PLUS MEMBERSHIP |
Home » Forums » AskWoody support » Productivity software by function » Visual Basic for Applications » INI File Manipulation Mess
>Exactly how would I call this function from the earlier version of my macro?
You’re not the only ignorant one. I was unsure of how you felt about your coding/reading skills. I mean that in the nicest way. When two (or more) people start communicating on a topic, there’s a period of adjustment as we discover each other’s level of understanding.
You could look through your macro and locate the places where are defined/described (1) the INI file name (2) the section name (3) the key name for the maximum number of entries etc and place a call to my function using those values.
For an example of a call to my function, look at the embedded TEST SUBroutine in the foot of my function, one line of which I reproduce below:
MsgBox intRemoveKey(“d:20010330script2k.ini”, “series”, “series”, “numseries”, 3)
I have just pulled these two lines from your supplied BAS file:
INIFile$ = WordBasic.[GetDocumentVar$]("inifile") Section$ = "Series"
so somewhere below this you’ld have a call that (partially completed) looks like this:
MsgBox intRemoveKey(INIFile$, Section$, etc. etc. etc.
Be warned: If you want to use my strGP/strPP functions (and I think they’re pretty good and I use them all the time) you’ll need to search for them in the VB/VBA forum and obtain them and their associated support functions. It’s not complicated.
Or as I suggested before, you could roll-your-own. Those “GetPrivateProfileInt” chunks ought to be embedded in neat little cover functions, IMNSHO (In My No So Humble Opinion).
Do I still get the button and the paperback?
Send us a toughie next time.
Here’s a solution using my INI file management routines strGP and strPP functions posted some weeks ago. My strGP/strPP are cover functions for accessing INI files. You could write your own strGP/strPP and access the registry. I have not tested this algoritm (below) for use via the registry.
Public Function intRemoveKey(strFile As String,_ strSection As String, _ strKey As String, _ strKeyMax As String, _ intKeyRemove As Integer) As Integer ' Procedure : intRemoveKey ' Description: Remove a key from the INI file. ' Copyright: Chris Greaves Inc. ' Inputs: STRING file name of ini file ' STRING section name within ini file ' STRING key name within section ' STRING name of key containing maximum key number ' INTEGER key to be deleted. ' Returns: A variant array of strings. ' Assumes: None. ' Side Effects: None. ' Tested: By the calls shown below. ' Method (an approach which lends its components to other appliactions) ' (1) Load an internal array with all relevant keys from the INI file. ' (2) Filter the nominated key during loading. ' (3) Write the array back to the INI file. ' String array to hold the keys and values from the INI file. Dim strArrayKey() As String ReDim strArrayKey(0) ' (1) Load an internal array with all relevant keys from the INI file. Dim intMaxKeys As Integer ' Obtain the current limit of keys intMaxKeys = Val(strGp(strFile, strSection, strKeyMax, 0)) Dim intKey As Integer ' Loop to load the array of keys For intKey = 0 To intMaxKeys ' (2) Filter the nominated key during loading. If intKey intKeyRemove Then ' load the key to the array strArrayKey(UBound(strArrayKey)) = strGp(strFile,_ strSection, strKey & Trim(str(intKey)), "") ReDim Preserve strArrayKey(UBound(strArrayKey) + 1) Else ' ignore the key End If Next intKey ReDim Preserve strArrayKey(UBound(strArrayKey) - 1) ' (3) Write the array back to the INI file. For intKey = 0 To intMaxKeys - 1 Call strPP(strFile, strSection, strKey & Trim(str(intKey)),_ strArrayKey(intKey)) Next intKey Call strPP(strFile, strSection, strKeyMax, UBound(strArrayKey)) 'Sub TESTintRemoveKey() 'MsgBox intRemoveKey("d:20010330script2k.ini", "series", "series",_ "numseries", 3) 'End Sub End Function
I have tested this, and can think of several improvments, but have held off until your comments arrive. I can make the code more robust and add features.
You can obtain my mailing address (for the free T-shirt, beer-mug, shrink-wrapped copies of VB6 etc from my home page, a link to which is conveniently provided at the foot of this post.
Oh yeah. One last thing. Don’t breathe a WORD of this outside of Woody’s Lounge. I have a reputation and it will suffer horribly if those who worship me discover that I’ve been dabbling in Comic Books (grin!)
>The various functions call for “inputs.”
No. Those comment lines at the head of the procedure are to remind me in a general way of the parameters required by the function. For example, the function “strAlphaOnly” takes as a parameter “‘ Inputs: A data string.”, i.e. some string of characters. If you look at the TESTstrAlphaOnly function, you’ll see some examples of the strings being passed to the function.
>which variable should correspond to which input data — e.g., “strFileVal: name of INI file”.
Thank you for this. You are quite right. I tend not do do that with functions that have two or less parameters, and then I forget to do it with functions that have more.
>Do I need to create a strDigitsOnly function
Yes. Oh great caught-on-one. A simple exercise since you already have strAlphaOnly. When done you could serach the VB/VBA lounge (“search” at top of your screen) for “strdigitsonly” I just posted it.
> but the process left behind a blank Series8 key
Yup. Gonna happend. I did not write this version for absolute cleanliness. Since you already have a “Number” key, I don’t need to do housekeeping.
If you didn’t want blank keys, I have at least two strategies (1) have me read the INI file as a plain text file and physically remove the key entry or (2) use but one key for the entries, and build the key as a set of delimited strings (I have utility functions that assemble and split strings) so that the key would look like this:
Series=Nevada, Slam Punjab, Last Son of Earth, Ace Brazil, Magda Queen of Gnats
>This one did nothing to the INI file, and I can’t figure out why.
Er. Ahem. Did you close and reopen Notepad while running the test? (How do I phrase this delicately so as not to miss out on the beer, mug, the unwrapped lady, the wet t-shirt, …).
I open the INI file in Notepad and inspect it. I run the test. I alt-tab back to the INI file. Nothing has changed (because I’m looking at a stale copy of the INI file).
I open, inspect and close the INI file. I run the test. I open & inspect the INI file and see the changes.
Thanks for persevering, and for your valued comments.
I make great use of INI files for the environment of the applications. Don’t be waylaid by arguments (good ones, too!) about INI vs. Registry. If you decide to go the registry route later on, it’s but a small change to these two functions, and all the code in all your applications remains untouched.
I’m asking another member of VB/VBA forum to confirm this. (not by actually doing it, but by comparing my code with theirs to see that it’s a small change in a cover function).
> create a file called eraseme.ini (not SECTION1.INI or SECTION2.INI) in the template directory, with the following contents.
… and by now you’ve worked this out, I hope.
The TEST subroutines supplied with each function aim at little more than establishing that a function does SOMETHING. A second use for them is to single-step (in debug mode) through the execution of code to watch the pulleys going around, the pistons going up and down (or down and up for our Aussie readers) etc.
>I get a “Subscript Out of Range” error a
This too? (or in Latin “Es Too Brtuus force approach?”)
I think I warned (very fine print) in the initial posting that “I have tested this, and can think of several improvments,” One of them was to make the routines more robust.
Since the INI file is available to the user, it could easily become corrupted. Complete code would test to see that there really WERE as many keys as specified and check a whole lot of stuff.
I was mainly wanting to let you see that there IS a solution. You can use my code ONLY as an idea to draft your own.
Chris,
>How do you know he doesn’t have more than 100 comic books in his collection?
You’re right.
I gather it’s more like 100 series rather that 100 books. But I suspect if you had that many, you’d want to organise them rather than show a listbox with a huge number of entries.
Doing it that way was a short cut which eliminated some of the string manipulation requirements. A quick and nasty.
If I wanted to have a more flexible solution, I would look at getting rid of the “ProfileString” stuff altogether, and just treat it like a sequential file. That would give me the complete flexibility of reading through as many entries as might be required, and not be restricted by the “ProfileString” stuff. It would be simple.
My method also had a noticable time lag.
The intent was just to attack from another side. Devil’s Advocate stuff.
> Doing it that way was a short cut – A quick and nasty.
I know. I was just yanking your chain! I realised after I posted that I often use a literal string in place of my well-defined string constants, mainly for readability in the post, also so as not to confusauser more than necessary.
> just treat it like a sequential file.
Right. Why aren’t we accessing even a flat-file Access data base here?
>Devil’s Advocate stuff.
Hey! That’s MY job !!!!!!
> to turn a comma-delimited key value into an array,
Scare not. I’m sure I have such a function somewhere here; and if I don’t, I ought. This discussion comes just as I am revising my ideas as to how I might store WhiteSpace characters. Several of my interests squeeze White Space which is – spacebar, tab, carriage-return, line-feed etc. I currently store these definitions as WhitSpace01, WhiteSpace02 etc in an INI file – just as your entries. I need to revamp this anyway. You may as well benefit.
> hint or two how I could go about eliminating those empty keys?
Sure. Read the INI file into an array; drop those entries which terminate in an equal sign; write the array over the top of the INI file.
You will find out how to REDIM PRESERVE an array in my earlier example. You will find how to open a file in PrintFile (use Search on this forum).
>Can you stand the suspense?
It’s to die for …..
> really is an error in your description of what the test routine is supposed to do:
(ulp!). You see. I’m not infallible.
You are quite correct. I tarted up the test routines for public consumption and forgot to upgrade the comments. people actually READ my comments? Egad!.
I’ve corrected them.
>GetArray:
STRING_MAX = 255
intKeyMax = (GetPrivateProfileInt(Section, “NumSeries”, 1, INIFile))
ReDim ListBox1__$(intKeyMax)
My guess is that you are REDIMming an array to one more than you need.
Try single-stepping through the macro as it executes. Continue to check the contents of your array in the Locals Window (View, Locals in VBE)
> This is the line of code (in the StrPP function) that’s writing the 9=8 line:
> Call apiPutPrivateProfileString(strSect, strKey, strValue, str)
That tells us that at the time that statement is executed strKey has the one-character string value “9” and strValue has the one-character string value “8”.
When you single-step through the code, what makes strKey take on “9”?
I know that this is laborious, but apart from re-writing your Wordbasic code (which would probbaly strip it down to about ten lines), you’re going to have to join the “debugging old code” brigade. Welcome!
Steve,
A couple of things you can do to reduce wear and tear:
Run to cursor: click an insertion point in the line of code you want to run to, then Ctrl+F8 to run to the line containing the insertion point (the code will go into break mode before executing that line). You can then continue by using F8, or click another insertion point and Ctl+F8 to run to cursor again.
Set a breakpoint: click in the gray lefthand border of the code window, next to any line you want the code to stop at. You’ll get a brown ‘blob’ and the line of code will highlighted brown too. If you use F5 to run the procedure, it will stop (enter break mode) anywhere you’ve set a breakpoint.
Also have a look at Step Over and Step Out – these are handy for speeding through a function that is called from your main procedure.
Gary
Good thinking, but I prefer to re-set the filename every time.
Many of my applications are table-driven, and get their environment variables from INI files. At least one ap that i can remember, the Document Cleanser, has a rules table that allows you to switch INI files while the job is running. Thus one can build a table of rules that translates, say, Spanish stuff, another table of rules for french, etc, and have the ap switch its environment FILE (that is, start getting INI values from a different INI file) as it runs.
There may be place sin code where i really could preserve the name in a local variable, but I’m usually too busy doing something else to worry about it. I speed up code when someone pays me to do it!
> think I’ll leave you in peace for a little while a
I think I speak for all here when I say:
If you disappear and shut up we’ll spam you with top-quality literary works like “Story of My Life by Helen Keller” and “THE VARIETIES OF RELIGIOUS EXPERIENCE – A Study in Human Nature BY WILLIAM JAMES “.
Your name will by Mudd in the fantasy world of coloured graphics.
We already have your email address, and by 9 a.m. this morning I will have your TWO postal addresses and will start filling out those cards that Kevin has been tearing out of magazines in Dentists Waiting Rooms.
Also those AOL CDs.
I am now working on a bio-metric text analyser that will surf the Lounge every hour looking for syntactically correct and varied texts from you. Three successive sweeps with no posting will initiate the mechanism outlined above.
Also once I get your telephone number, my DOS dial-attacker swings into action:
REM Attack.bat call dial 416-256-6481 call dial 905-761-6774 call dial 416-253-7382 call dial 416-439-0224 %0
I normally reserve execution of this batch file for people who dial a wrong number and then hang up without apologising, but in your case I’ll make an exception.
I think we understand each other …..
> Actually, I have run into another VBA mystery:
>> >my DOS dial-attacker swings into action:
You thought I was JOKING!?????
Hah!
OK. Changing the names to remove the suffix “$” might have alerted the WordBasic interpreter to the identifiers no longer being STRING identifiers, and therefore they must be numeric.
So maybe whatever you loaded into the elements was co-erced into numeric?
You could set up a little epxeriment to prove this.
I suspect that you haven’t used any sort of type declaration in the old code; you have stuff like this:
dim MyString
rather than this:
dim MyString as String
>this only happens (so far) with arrays
So. Run a little experiment with arrays. Takes about three minutes. Just to satisfy yourself that that can cause a problem. Then when you spot that a week from now it won’t cost you an hour; you’ll know straight away you’re heading for the reefs.
>declare an array whose members are all text as a string or a variant?
STRING. I have a general dislike for undeclared variabls in any language. I know that there will be times to use variants in VBA; my most common use is when I’m learning a new object. Bottom line is “If you don’t know what you want it for, why are you using it?”.
>as a carpet cleaning service?
call dial 416-293-4383
Caught these folks yesterday trying to sell me Duct Cleaning “while the truck is in your neighbourhood” while **I** was trying to eat my only hot meal of the day. Of course, I’ll have to make several essays to determine just what time of day THEY eat their hot meal…..
> put the array routines into a separate module
Why would this have any impact on them being declared un-typed?
I can put an array in a separate module and declare it as a STRING array that is available throughout the Word97/VBA application. The question here is not one of scope/domain (which you have posted more recently and I have responded just now) but of type.
I have no doubt that a survey of users would reveal a great many people using un-typed Variants. I’m pretty sure that many of Word’s supplied functions/methods/properties insist on this.
I’d be interested to hear who is using variants for local (not constrained by Word) purposes, and their justification for this. The resons would mainly be good. Just that I’ve not found a need to go there yet, and, I suspect, neither have you.
>burning bush said, “I am that I am.”
You guys didn’t wait much beyond the first 100 days, eh?
Donations from Plus members keep this site going. You can identify the people who support AskWoody by the Plus badge on their avatars.
AskWoody Plus members not only get access to all of the contents of this site -- including Susan Bradley's frequently updated Patch Watch listing -- they also receive weekly AskWoody Plus Newsletters (formerly Windows Secrets Newsletter) and AskWoody Plus Alerts, emails when there are important breaking developments.
Welcome to our unique respite from the madness.
It's easy to post questions about Windows 11, Windows 10, Win8.1, Win7, Surface, Office, or browse through our Forums. Post anonymously or register for greater privileges. Keep it civil, please: Decorous Lounge rules strictly enforced. Questions? Contact Customer Support.
Want to Advertise in the free newsletter? How about a gift subscription in honor of a birthday? Send an email to sb@askwoody.com to ask how.
Mastodon profile for DefConPatch
Mastodon profile for AskWoody
Home • About • FAQ • Posts & Privacy • Forums • My Account
Register • Free Newsletter • Plus Membership • Gift Certificates • MS-DEFCON Alerts
Copyright ©2004-2025 by AskWoody Tech LLC. All Rights Reserved.