PDA

View Full Version : Solved: Find paragraph that may contain several formfields?



DaVinney
03-08-2011, 04:50 PM
Hi,

Please let me know if there's a way to have VBA find a single paragraph that may contain one or more formfields which may or may not have values entered. I've been able to find such a paragraph by looping thru the document comparing text strings, but seems to work only when all fields are blank (no values entered).

Example (paragraph displaying field codes [Alt-F9]):


The paragraph may have a { FORMCHECKBOX } field or a {FORMTEXT } field or a { FORMDROPDOWN } field or any combination, but none of the fields have known bookmark names.


Doing tests in the Find/Replace dialog, I've been able to locate such a paragraph using strings containing, for example: '^d FORMCHECKBOX ^?'
The above example paragraph is found using:

The paragraph may have a ^d FORMCHECKBOX ^? field or a ^d FORMTEXT ^? field or a ^d FORMDROPDOWN ^? field or any combination, but none of the fields have known bookmark names.

But this sort of format does not find the subject paragraph using any sort of Find/Replace routine I try.

Again, I would like the method to be transparent to whether or not the field has any data entered.

Any insight? Thanks

Frosty
03-08-2011, 06:54 PM
Does something like this help?

Public Sub IterateThroughFormFields()
Dim oDoc As Document
Dim oField As FormField
Dim sMessage As String

Set oDoc = ActiveDocument
For Each oField In oDoc.FormFields
Select Case oField.Type
Case wdFieldFormCheckBox
sMessage = "It's a checkbox"
Case wdFieldFormDropDown
sMessage = "It's a drop down"
Case wdFieldFormTextInput
sMessage = "It's a input"
Case Else
sMessage = "I dunno!"
End Select
If MsgBox(sMessage, vbOKCancel, "Keep going?") = vbCancel Then
oField.Range.Select
Exit For
End If
Next
End Sub

Frosty
03-08-2011, 06:56 PM
If you need to figure out the paragraph the particular field is in... you can always...

Dim oPara as Paragraph
.... somewhere down in the code ....

set oPara = oField.Range.Paragraphs(1)

DaVinney
03-08-2011, 07:35 PM
Thanks for the response, Frosty.

hmm...I can't figure how your suggestions can help me. Maybe this is a clearer way for me to ask my question...

Let's say you place the example paragraph somewhere in a large document:

The paragraph may have a { FORMCHECKBOX } field or a {FORMTEXT } field or a { FORMDROPDOWN } field or any combination, but none of the fields have known bookmark names.

(Except, of course, instead of the brackets as shown above , the paragraph has the actual fields (containing form data in each)).


So, my question would be, how can I search out that specific paragraph using VBA code, select it, and then do something with it such as change its color?

The root of the problem is that the fields in the search documents have data entered in them and that is throwing off any methods I can think of to find such paragraphs. All other paragraphs I can hunt down no problem.

Frosty
03-08-2011, 08:11 PM
Hmm, we're clearly not communicating. I don't understand you any better now than I did in your first post. Maybe you should try to post a sample document (I think you'll need 5 posts before you can).

Rather than try to post what you think is "mostly" the solution if you only knew one more little bit, why don't you try to give the 10,000 foot view of what you want to do.

Because right now I think you have a sample paragraph with exactly the following text:
The paragraph may have a { FORMCHECKBOX } field or a {FORMTEXT } field or a { FORMDROPDOWN } field or any combination, but none of the fields have known bookmark names.

And you want to know how to find that exact paragraph... but you already know about ^d. So I'm guessing there is some other kind of search criteria... perhaps a paragraph which has 3 form fields in it, but in any particular order? Well, my sample code would help you if you actually step through it... unless you are not a programmer at all, in which case you need to give a really clear picture of the before and after-- no client data, of course, but something a little more concrete than "some text, some fields, some paragraphs and some colors." Grin.

DaVinney
03-08-2011, 09:15 PM
If I run a snippet of code like this on a batch of say 50 document files with the goal of turning a specific string (pSearchTxt) red, it works across the board, even if the string contains fields so long as they are empty fields. But the code does not work if the string has fields that contain data. If there is any data in any of the fields in the string, the code overlooks the target string.


Dim pSearchTxt As String
Dim vTxt As Variant
Dim i As Long
vTxt = ActiveDocument.Content.Text
vTxt = Split(vTxt, vbCr)
For i = LBound(vTxt) To UBound(vTxt)
If vTxt(i) = pSearchTxt Then
ActiveDocument.Paragraphs(i).Range.Font.Color = wdColorRed
Exit For
End If
Next


So, I'm searching for code that will also work when the search string has fields that contain data.

Hope that helps clarify. BTW, I'm a VBA novice.

Frosty
03-09-2011, 08:35 AM
Looks like you're a vba novice, but not a programming novice.

I'm not surprised your methodology breaks down when fields are involved... it would probably break down if you had tables involved as well.

The Split function creates a string array... so anything which can't be held in a string is going to be tossed out in your string comparison (i.e., fields with no data get tossed out, fields with data will show their .Result in string form).

I don't know what your documents look like, but if this is the only sticking point you've run into with this methodology, they must be pretty simple. I would think there are at least a couple of ways to go on this:

1. Since you're only looking once and exiting (meaning your search string is unique to the document?), you could, in the same loop, just put an else in there, and if the search string didn't match your array element, look in the actual paragraph to see if a .Fields.Count > 0... and decide whether you need to do additional processing. I'm not a fan of this approach, but it might be the least impactful, depending on the rest of your code and the style of your documents.

2. Use the actual .Find object (which will allow you to use the ^d code to find fields), and then know that when the .Find executes, it will modify the search range to the found range... if it can. So...

ActiveDocument.Content.Find is not going to help you, but
dim rngSearch as Range
Set rngSearch = ActiveDocument.Content
rngSearch.Find

will help.

From there, if you have a successful search... you'll have a range which encompasses your found text. Then you can (assuming you've had a successful search) grab additional objects off of your found range to get the entire paragraph, like so:
rngSearch.Paragraphs(1).Range.Font.Color = wdColorRed

I have a feeling using #2 (the Find object) is going to speed up your processing a good bit as well, since it is a very optimized class compared with breaking your document down into a single array split by paragraphs, and then string comparing each paragraph string with your search string.

You can also read up on Working with Ranges in the VBA help. That, combined with a recorded Find macro (don't worry about the replace... all you need is the returned range of a successful search), should give you a solid methodology.

Frosty
03-09-2011, 08:40 AM
Thought of a third method, although it too has scenarios where it will break, so #2 (i.e., working with the actual document is good)...

#3. Take the entire document, copy the range, paste it into a new (temporary) document... then take my "iterate through form fields" code above, and just delete the range of the fields. Then you can do you do your string comparison (which is really only designed to get you a paragraph # anyway) without worry of what (if anything) is contained in the field.

If you want to post a sample document of the *kind* of text/searchstring you're actually using, I might be able to help more... but the generic "use the find object" or "use a logical branch to determine if you have formfields in the particular paragraph" are about the only general responses I can give.

Find object use is easy to play with in a recorded macro... and you clearly have programming experience, so you just need to know about objects you don't already know about, I think.

fumei
03-10-2011, 09:56 AM
You mean like this? Click "Which Paragraph Has FF". Messagebox displays with...which paragraph has formfiedls.

7 lines of simple code. No need to test text strings at all.

BTW: WHY do your formfields not have bookmarks?? I take you copied them.

DaVinney
03-10-2011, 08:35 PM
Thanks, Frosty, for your suggestions. I ended up going with your Method #2. That was the missing link of info to get me the desired result. I can find the paragraphs I need, regardless of whether the formfields contain data. Works well for my needs. I will soon be a (temporary) hero at my office :bow:


Fumei, I'll be taking a look at your attachment. I meant the hundreds of default field bookmarks are not useful to what I needed.

fumei
03-14-2011, 10:13 AM
"Please let me know if there's a way to have VBA find a single paragraph that may contain one or more formfields which may or may not have values entered. "

Yes, there is a way, and you do no need to use string testing, nor any use of Find. Nor is it based on whether there is a value in the formfield (or not). Like this (click "With FF" on toolbar): 5 lines of code.

"The paragraph may have a ^d FORMCHECKBOX ^? field or a ^d FORMTEXT ^? field or a ^d FORMDROPDOWN ^? field or any combination, but none of the fields have known bookmark names." If the bookmark names are not useful to you, why do you mention them?

DaVinney
03-14-2011, 02:28 PM
Yes, there is a way, and you do no need to use string testing, nor any use of Find. Nor is it based on whether there is a value in the formfield (or not). Like this (click "With FF" on toolbar): 5 lines of code.

"The paragraph may have a ^d FORMCHECKBOX ^? field or a ^d FORMTEXT ^? field or a ^d FORMDROPDOWN ^? field or any combination, but none of the fields have known bookmark names." If the bookmark names are not useful to you, why do you mention them? I'm using 2007, so I found the WithFF as an add-in. The 5 lines of code I'd like to see, but there is a pw.

You know how there is a default name (label) given to each formfield (when you double-click it)? The dialog says "Bookmark: __________" and labels them Check1, Check2, or Dropdown1, Dropdown2, etc. Well, I meant I can't reference the formfields I'm dealing with by those labels because there are thousands of them randomly named, created by someone else.

I mentioned ^d FORMCHECKBOX ^?, etc. to show the text string I was using in my string searches to locate formfields, but it wasn't working out for me when I first posted this topic.

fumei
03-15-2011, 10:58 AM
"Well, I meant I can't reference the formfields I'm dealing with by those labels because there are thousands of them randomly named, created by someone else."

When you use those names you are referncing the formfields, you are referencing the bookmarks, which is what those names are. So. You have thousands of formfields in this document? What do you mean randomly named. Ther are default names set when a formfield is created (but NOT when it is copied). It is not random.

To make them random (and I seriously doubt this is th ecase) someone whould have to go in and change them. Possible i suppose, but still not really relevant.

The formfield name and the bookmark name are the same value.

ActiveDocument.Formfields("ThisName") - the formfield name - means that the bookmark name (if it exists) is also "ThisName".

"Well, I meant I can't reference the formfields I'm dealing with by those labels "


I do not know how that is possible. If a formfield has a bookmark name (what you call a label), then you CAN reference it by that name.

fumei
03-15-2011, 11:00 AM
"The 5 lines of code I'd like to see, but there is a pw."

Here you go.
For Each oPara In ActiveDocument.Paragraphs
If oPara.Range.FormFields.Count > 0 Then
oPara.Range.HighlightColorIndex = wdBrightGreen
End If
Next
C'est tout.