Consulting

Page 3 of 3 FirstFirst 1 2 3
Results 41 to 59 of 59

Thread: Splitting a document into multiple documents

  1. #41
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Quote Originally Posted by Frosty
    5. Now, to your main question: the reason you're getting the wrong result is because that's exactly what you've told it to do. Remember, ranges are live addresses to something which is already in the document. So when you do the following:
    rngScrap.select
    rngScrap.Cut
    ... what is left of rngScrap?

    The same thing that is left when you select 3 paragraphs and cut them... an insertion point. So when you later do this:
    rngDocNew.FormattedText = rngScrap.Formatted text

    You've forgotten all about the stuff you had in your clipboard.

    rngDocNew.Paste would work.
    Well, DOH, I removed the .Cut, then, I ran the program. When it finished I looked in a file that should have 2 Activities and, lo and behold, it has both activities.

    The only problem left is that it (output file) has an extra Paragraph mark (symbol) at the end of the file. This suggests to me that after Finding the ^m and settng my range, I need to remove it. Then, when I add a 2nd activity to a file, I need logic to insert (prepend) a ^M to that second activity so there is a forced page break between the Activities instead of having one after every activity. Does that make sense?

    I'll look at cleaning up the code, removing debug code and .Selects.

    You're right, I probably do not need both ActivityStart and ActivityEnd but rather just one of them, ActivityEnd, so I can walk through the source file in an orderly manner.

    I'm passing a null (""") in initially in my Open_File sub and it will return a value that I'll use elsewhere, that's why a sub and not a function. I suppose for simplicity I could use a named variable which begins its life with no value and let it gain a value after the sub is run the first time.

    Let me look at some of your other suggestions and questions, I'll write a more complete response and post a file will all my code so you can see the whole mess.

    Thanks, again.
    Ron
    Windermere, FL

  2. #42
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    I would suggest, since you're getting so advanced... to forget the whole page break thing entirely, and simply format the first paragraph of your range to have a page break before. Use the pagebreak as your identifier to split your activities, but then dump it and use the pagebreakbefore formatting property.

    rngActivity.Paragraphs(1).ParagraphFormat.PageBreakBefore = True

    The funky thing about page breaks, is that they can really mess up the ease of working with ranges and paragraphs (in addition to occasionally giving you a blank page), since a page break is technically just a character, rather than also a paragraph break (as opposed to a section break... which is both a character mark and a paragraph mark combined). Without getting too esoteric... there are scenarios where you can have a single paragraph which looks like two paragraphs, because somewhere in the middle is a page break character. And this causes "bad" behavior because you will have formatting "bleed" from what part of a document to another.

    Fortunately, it looks like Word 2010 makes this harder to do in the user interface, by inserting some paragraph marks as well when you press CTRL+ENTER, but vba won't do that for you.

    Also, as an fyi... just because you want to return multiple parameters doesn't mean you need to have a subroutine... a very typical (for me) way of writing a function which returns multiple parameters is to have the function actually return a long (or a public enumerator I've set up) to indicate various states of "success", "failure", "no documents open", etc... while the passed in parameters actually return the objects/variables I need (if my function didn't return failure).

    It allows a very readable structure of

    Dim oNewLetter as Document

    'a routine which creates a new document based on a letter template, showing a form... but if the user hits cancel, the new document gets dismissed... and I have nothing)
    If fGetANewLetter(oNewLetter) = SUCCESS then
    'I do stuff with the oNewLetter
    End If

    To me this becomes easier than testing to see if oNewLetter = Nothing before doing other processing (it also allows me to separate out function returns from generic errors (I lost my document object) with normal operation (user hit cancel somewhere along, and I want to graciously exit my routines).

    But this is all theory... it's nice that you had the "DOH" moment. That means you got it!

  3. #43
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Quote Originally Posted by Frosty
    I would suggest, since you're getting so advanced... to forget the whole page break thing entirely, and simply format the first paragraph of your range to have a page break before. Use the pagebreak as your identifier to split your activities, but then dump it and use the pagebreakbefore formatting property.

    rngActivity.Paragraphs(1).ParagraphFormat.PageBreakBefore = True

    <snip>
    When the first paragraph of a document has the attribute .PageBreakBefore=True does Word know to not force a leading blank page?

    What's the easiest way to 'lose' the trailing page bread (^m)? Does it show up as a discrete paragraph that I can delete? Or, do I need look at the text of the last paragraph and trim it down by one character using something like the following?

    With oDocNew.Paragraphs(whateverthenumber).Range.
    .Text = Left(.Text, len(.Text)-1)
    End With

    Or, knowing the .End value I could only copy to End:=endvalue-1 and lose a byte that way?

    or, is it: rngActivity.Paragraphs(somenumber).ParagraphFormat.PageBreakAfter = False ??

    Hmmm?

    Thanks,
    Ron
    Windermere, FL

  4. #44
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    1. The .PageBreakBefore property (which you can see in the Paragraph Format dialog, Line and Page breaks tab) is smart enough to know not to put in a blank page. It simply makes sure that the paragraph it is applied to is at the "top" of a page.

    Quick concept lesson here, because of your last question (in addition to .PageBreakAfter not existing as a property):
    or, is it: rngActivity.Paragraphs(somenumber).ParagraphFormat.PageBreakAfter = False ??
    Page breaks are characters. The same way that "J" or "!" are characters. That means you have to insert them and remove them to change what they do (or to change the meaning of words... to change "Jason is Great" to "Jason is Fantastic"... you have to delete characters and insert characters.

    .PageBreakBefore is a property (i.e., formatting), the same way that "bold" or "underline" is formatting. You don't have anything to delete or insert... just something to change. If I were a class object, it would be something along the lines of Jason.Great = False, Jason.Fantastic = True.



    I know it seems like a minor point, but it's actually a pretty big conceptual issue. And the reason why I advocate formatting whenever possible, especially over a character with the sole purpose of "acting" like formatting (i.e., page breaks). Because it's such a pain to remove the stuff later.

    2. Easiest way to "lose" the trailing page break... great question. The answer is conceptual (especially since I don't have any code to look at). You have a function which returns your activity range, for the purposes of doing something (.cut, .copy, rngInsertWhereInNewDoc.FormattedText = rngActivity.FormattedText), right?

    That is where you should adjust it. Return the range you actually want to use from within the function that has that "job." If you've encapsulated properly... nothing else should really matter too much.

    So as for what to do with the trailing page break... you don't really need to delete it, since you don't really care about the source document (or the copy of the source document)... you just need a way of telling your loop to skip any page breaks it finds... which you do by adjusting the new search range.

    Changing a 1 character jump to a 2 character jump (or whatever is necessary) shouldn't be too hard, right?

    That said, since I think you're using the .Cut methodology, it's not hard to simply delete the one character left after the .Cut, if that's the way you need to articulate searching through the document.

    Let me know if some of that doesn't make sense.

    - Jason

  5. #45
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Jason, you are a GREAT addition to this site.

  6. #46
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Quote Originally Posted by fumei
    Jason, you are a GREAT addition to this site.
    He is good, isn't he!
    Ron
    Windermere, FL

  7. #47
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Quote Originally Posted by Frosty
    2. Easiest way to "lose" the trailing page break... great question. The answer is conceptual (especially since I don't have any code to look at). You have a function which returns your activity range, for the purposes of doing something (.cut, .copy, rngInsertWhereInNewDoc.FormattedText = rngActivity.FormattedText), right?

    That is where you should adjust it. Return the range you actually want to use from within the function that has that "job." If you've encapsulated properly... nothing else should really matter too much.

    So as for what to do with the trailing page break... you don't really need to delete it, since you don't really care about the source document (or the copy of the source document)... you just need a way of telling your loop to skip any page breaks it finds... which you do by adjusting the new search range.

    Changing a 1 character jump to a 2 character jump (or whatever is necessary) shouldn't be too hard, right?
    How's that, again? When I Find for a ^m, my code needs first to jump back one, to exclude the ^m from the selected Activity; after that, it can jump forward 2 so it leaves that ^m excluded while we find the next Activity.

    Quote Originally Posted by Frosty
    That said, since I think you're using the .Cut methodology, it's not hard to simply delete the one character left after the .Cut, if that's the way you need to articulate searching through the document.
    Initially, I misapprehended that I needed to move the Activity from my docScrap to docNew, hence, my use of .Cut. Now, I see that I don't need it since the code is implicitly pasting the Activity. And, I don't need to "empty" docScrap, all I need to do is .Paste the next Activity into it for my manipulating it. And, with a little extra thought I may be able to dump using docScrap and go straight from rngActivity to docNew.

    Well, time for me to work on a job application that's due by 11:59 pm, tonight. I'll get back on this topic when that's done or first thing in the AM.

    Thanks, again!
    Ron
    Windermere, FL

  8. #48
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    I think you can probably just get your activity range... and move the end of it back 1 (to define the range as not including the page break)... and at the same time, redefine the start of your search range to the end of your new activity range. Something conceptually like (this is pseudo code):
    [vba]
    'this would be outside of your loop-- essentially, your starting condition
    set rngSearch = ActiveDocument.Content

    'and then your loop of going through the document's activities
    do
    'use the external function to return the activity range, sans page break
    'while using .Duplicate in the function so that rngSearch doesn't get redefined
    set rngActivity = fGetMyActivityRange(rngSearch)

    if rngActivity.End <> oSourceDoc.Content.End then
    'keep going
    rngSearch.Start = rngActivity.End
    end if
    'and keep going until the found activity range is the end of the document
    loop until rngActivity.End = oSourceDoc.Content.End
    [/vba] Not trying to be a moving target... just trying to pseudo-code the concept.

  9. #49
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Jason,

    Quote Originally Posted by Frosty
    Not trying to be a moving target...
    Oh, sure you are.

    Well, I think I have this done and working. Here's my code. (I'm attaching a file, with trimmed down greeked data as well as this code.)

    [vba]Option Explicit
    Option Base 0
    Sub Select_MyActivity()
    Dim Grade As Long
    Dim Unit As Long
    Dim MaxUnit As Long
    Dim MySrcFile As String
    Dim MyOrigFile As String
    Dim ActivityStart As Long
    Dim ActivityEnd As Long
    Dim rngLookWhere As Range
    Dim rngSearch As Range
    Dim rngActivity As Range
    Dim rngScrap As Range
    Dim myRange As Range
    Dim oDocSource As Document
    Dim oDocNew As Document
    Dim rngDocNew As Range
    Dim oDocScrap As Document
    Dim myOutFile As String
    Dim MyFileExten As String
    Dim MyFileType As String
    Dim File_Saved As Boolean
    Dim LastFileName As String
    Dim SrcDir As String
    Grade = 1
    Set oDocScrap = Documents.Add
    Do While Grade <= 5

    Unit = 1
    Grade = 5 ' dev code
    Unit = 3 ' dev code
    MaxUnit = GetMaxUnit(Grade)

    Do While Unit <= MaxUnit

    SrcDir = ChangeToSrcDir(Grade, Unit, SrcDir)
    MySrcFile = Get_SrcFileName(Grade, Unit)
    Call Open_File(MySrcFile, "MySrcFile", "", SrcDir)
    MyOrigFile = Get_OrigFileName(Grade, Unit)
    Call Save_OrigFile(MyOrigFile, "MySrcFile", MySrcFile, SrcDir)

    Set oDocSource = ActiveDocument
    Do Until ActivityEnd = oDocSource.Content.End
    Set rngActivity = Find_MyActivity2(oDocSource.Content, rngActivity, ActivityStart, ActivityEnd)
    'find it and select it
    myOutFile = Get_MyOutFile(rngActivity)
    rngActivity.Copy
    oDocScrap.Range.Paste
    Set rngScrap = oDocScrap.Content
    Set rngScrap = Delete_1stLine(rngScrap)
    rngScrap.Copy
    If myOutFile <> LastFileName Then
    Set oDocNew = Documents.Add
    oDocNew.Range.Paste
    Else
    Call Open_File(myOutFile, "MyOutFile", "", SrcDir)
    Set oDocNew = ActiveDocument
    Set rngDocNew = oDocNew.Content
    rngDocNew.Collapse Direction:=wdCollapseEnd
    rngDocNew.FormattedText = rngScrap.FormattedText
    End If
    File_Saved = Save_oDocNew(oDocNew, "MyOutFile", myOutFile, SrcDir)
    If File_Saved <> True Then
    Stop
    Else
    LastFileName = myOutFile
    End If
    oDocNew.Close SaveChanges:=False
    Loop
    Unit_Done:
    Unit = Unit + 1
    oDocSource.Close SaveChanges:=False
    LastFileName = ""
    Loop
    Grade_Done:
    Grade = Grade + 1

    Loop
    End Sub

    'returns the maximum unit number in a grade
    Function GetMaxUnit(Grade As Long) As Long
    Dim MyUnit As Long
    Select Case Grade
    Case 4
    MyUnit = 11
    Case 5
    MyUnit = 15
    Case Else
    MyUnit = 10
    End Select
    GetMaxUnit = MyUnit
    End Function
    'Changes to SrcDir, if SrcDir = null then gets SrcDir
    Function ChangeToSrcDir(Grade As Long, Unit As Long, myDir As String) As String
    If myDir = "" Then
    myDir = get_SrcDir(Grade, Unit)
    End If
    ChangeFileOpenDirectory myDir
    ChangeToSrcDir = myDir
    End Function
    Function get_SrcDir(Grade As Long, Unit As Long) As String
    Dim myDir As String
    Dim NewDir As String
    myDir = _
    "C:\Documents and Settings\mckenzier\Desktop\G1-5 NL 2012 Inquiry Support files for DCD\G" & Grade & "\"
    NewDir = Assign_UnitNo(myDir, Unit)
    NewDir = NewDir & "\"

    NewDir = "C:\Users\Ron\Desktop" & "\Unit-Test\" ' for laptop
    get_SrcDir = NewDir
    End Function
    Function Get_SrcFileName(Grade As Long, Unit As Long) As String
    Dim MyFile As String
    MyFile = "G" & Grade
    MyFile = Assign_UnitNo(MyFile, Unit)
    Get_SrcFileName = MyFile & "_InquirySupport"
    End Function
    Function Assign_UnitNo(myStr As String, Unit As Long)
    If Unit < 10 Then
    myStr = myStr & "U0" & Unit
    Else
    myStr = myStr & "U" & Unit
    End If
    Assign_UnitNo = myStr
    End Function
    Sub Open_File(MyFile As String, MyFileType As String, MyExten As String, MySrcDir As String)
    ' err.number = 5174 ' for file not found
    Dim MyFileFormat As String
    Call Get_FileExten_Format(MyFileType, MyExten, MyFileFormat)
    Documents.Open FileName:=MySrcDir & "\" & MyFile & MyExten, ConfirmConversions:=False, _
    ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:="", _
    PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _
    WritePasswordTemplate:="", Format:=wdOpenFormatAuto, XMLTransform:=""
    End Sub
    Function Get_MyOutFile(rngAnActivity As Range) As String
    Dim MyFile As String
    Dim GrUnLsn As String
    Dim MyArray As Variant
    ReDim MyArray(3) As String
    ' This is debug code that I'm leaving in to catch formatting errors.
    If InStr(rngAnActivity.Paragraphs(2).Range.Text, "Grade") = 0 Then
    Stop
    Debug.Print rngAnActivity.Paragraphs(1).Range.Text
    Debug.Print rngAnActivity.Paragraphs(2).Range.Text
    Debug.Print rngAnActivity.Paragraphs(3).Range.Text
    Debug.Print rngAnActivity.Paragraphs(4).Range.Text
    End If
    MyFile = rngAnActivity.Paragraphs(1).Range.Text
    ' This code is for locating unexpected formatting of data
    If InStr(MyFile, "NL") <> 1 And InStr(MyFile, "NL") > 0 Then
    MyFile = Mid(MyFile, InStr(MyFile, "NL"), Len(MyFile) - InStr(MyFile, "NL") + 1)
    Else
    If InStr(MyFile, "NL") = 0 Then
    Stop
    End If
    End If
    MyFile = Left(Trim(MyFile), Len(MyFile) - 1)
    GrUnLsn = rngAnActivity.Paragraphs(2).Range.Text
    GrUnLsn = Left(Trim(GrUnLsn), Len(GrUnLsn) - 1)
    MyArray = Split(GrUnLsn, ",")
    ' MyArray = Split("Grade 5, Unit 3, Lesson 1", ",")
    ' And then MyArray would be
    ' MyArray(0) = "Grade 5"
    ' MyArray(1) = "Unit 3"
    ' MyArray(2) = "Lesson 1"
    MyArray(0) = Right(Trim(MyArray(0)), 1)
    MyArray(1) = LTrim(Right(RTrim(MyArray(1)), 2))
    MyArray(2) = Right(Mid(MyArray(2), 2, 8), 1)
    Get_MyOutFile = MyFile & " G" & MyArray(0) & " U" & MyArray(1) & " L" & MyArray(2)
    End Function
    Function Delete_1stLine(rngMyScrap As Range) As Range
    Do While Len(rngMyScrap.Paragraphs(1).Range.Text) < 10
    rngMyScrap.Paragraphs(1).Range.Delete
    Loop
    rngMyScrap.Paragraphs(2).PageBreakBefore = True
    rngMyScrap.Paragraphs(1).Range.Delete
    Set Delete_1stLine = rngMyScrap
    End Function

    Function Find_MyActivity2(rngLookWhere As Range, rngAnActivity As Range, ActivityStart As Long, ActivityEnd As Long)
    If ActivityEnd > 0 Then
    ActivityStart = ActivityEnd + 2 ' + 2 to get past the ^m of the prior Activity
    rngLookWhere.start = ActivityStart
    End If
    With rngLookWhere.Find
    .Text = "^m"
    'if we found our page break,reset the beginning of our found range to the original start
    If .Execute = True Then
    ActivityEnd = rngLookWhere.End
    ActivityEnd = ActivityEnd - 1 ' Do not copy the ^m when I paste
    Else
    ActivityEnd = rngLookWhere.End
    End If
    End With
    Set Find_MyActivity2 = rngLookWhere.Document.Range(start:=ActivityStart, End:=ActivityEnd)
    End Function
    ' Save the file but leave open for the moment
    Function Save_oDocNew(oDocNew As Document, MyFileType As String, MyFileName As String, SrcDir As String) As Boolean
    Dim MyExten As String
    Dim MyFileFormat As String
    If Right(SrcDir, 1) <> "\" Then
    SrcDir = SrcDir & "\"
    End If
    Call Get_FileExten_Format("MyOutFile", MyExten, MyFileFormat)

    ActiveDocument.SaveAs FileName:=MyFileName & MyExten, FileFormat:=wdFormatRTF, _
    LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
    :="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
    SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
    False

    Save_oDocNew = True
    End Function
    Sub Get_FileExten_Format(MyFileType As String, MyFileExten As String, MyFileFormat As String)
    Select Case MyFileType
    Case "MySrcFile", "MyOrigFile"
    MyFileExten = ".doc"
    MyFileFormat = "wdFormatDocument"
    Case "MyOutFile"
    MyFileExten = ".rtf"
    MyFileFormat = "wdFormatRTF"
    Case Else
    MyFileExten = ".doc"
    MyFileFormat = "wdFormatDocument"
    End Select
    End Sub
    Function Get_SrcFileName2(Grade As Long, Unit As Long) As String
    Get_SrcFileName2 = "G" & Grade & "U" & Unit & "_InquirySupport.Doc"
    End Function
    Function Get_OrigFileName(Grade As Long, Unit As Long) As String
    Dim OrigFile As String
    OrigFile = "IS_G" & Grade & "U"
    If Unit < 10 Then
    OrigFile = OrigFile & "0" & Unit
    Else
    OrigFile = OrigFile & Unit
    End If
    OrigFile = OrigFile & "_WorkingCopy"
    Get_OrigFileName = OrigFile
    End Function
    ' Save the file but leave open for the moment
    Function Save_OrigFile(MyOrigFilename As String, MyFileType As String, MyFileName As String, SrcDir As String) As Boolean
    ' MyFileType as String, MyExten as String, MyFileFormat as String
    ' e.g. MyOutFile .rtf wdFormatRTF
    ' MySrcFile .doc wdFormatDocument
    Dim MyExten As String
    Dim MyFileFormat As String

    Call Get_FileExten_Format("MyOrigFile", MyExten, MyFileFormat)
    ActiveDocument.SaveAs FileName:=SrcDir & MyOrigFilename & MyExten, FileFormat:=wdFormatDocument, _
    LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
    :="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
    SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
    False
    Save_OrigFile = True
    End Function[/vba]

    Thanks for all your advice, counsel, assistance, and patience.

    And, here's the file for your edification and review.

    Cheers,
    Attached Files Attached Files
    Last edited by RonMcK; 03-12-2011 at 08:03 PM.
    Ron
    Windermere, FL

  10. #50
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Jason, MC, Fumei, and all you lurkers.

    As I've used my "program," I've discovered that my users are busily finding ways to thwart my process.

    When we last looked at this, my code was searching for inserted page breaks by looking for "^m" characters.

    I now find that my users sometimes insert what I'll call a 'soft return' instead of just pressing enter to get a CrLf. In addition, when I asked them to insert a manual page break (that ^m), some of them entered a Section Break, instead.

    MY CURRENT REQUEST: What are the control-key equivalents (or other identifiable code) that I need to search and test for soft returns, section breaks, and any other common code, so, I can maintain a semblance of control over my process??

    Thanks,
    Ron
    Windermere, FL

  11. #51
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Ah, those pesky end-users. Always screwing up the perfectly programmed routines.

    A great example of why separating out functions is so useful. Would it be safe to say (since your sample document doesn't contain all the variations you identified) that your main problem, at the moment, is that your FindActivity2 function is failing some times?

    If that's the case, I'm going to rewrite that one for you.

  12. #52
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Frosty,

    That a good summary. One recurring issue is that the text for paragraphs 1 & 2 sometimes shows up in paragraph 1 because paragraph 1 is not properly "terminated". The other issue is that several activities get picked up at one time because a section break instead of a page break (^m) was used after the heading "Notes:" so my program picks up multiple activities not all of which are related (below to the same lesson).

    I've been giving thought to writing a set of routines that will read through the source file, correct errors in it and, then, write out a clean source document.

    The source (original) file is part of the records we are retaining in a versioning system so we have a beginning point for the next edition of these documents.

    Thanks,
    Ron
    Windermere, FL

  13. #53
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    I think that's probably unnecessary. The flaw is in the identification of your single activity-- so focus on making that function as robust as possible. Just in a quick glance, I think there's a relatively small footprint way to improve, but I have a question: are all of your activities started by some variation of "NL_yadayada" ... or are there other bits of prefixed text (i.e., I think it might be beneficial to identify the "start" of an activity, rather than the "end" of one)

  14. #54
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Frosty,

    At the moment, the first line of an Activity can begin with
    • NL_Gn_XX_#####_blah or
    • FL_Gn_XX_#####_blah or
    • IN_Gn_XX_#####_blah
    These are the easy ones.

    The tough ones begin:
    • LO Name: Gn_XX_#####_blah
    and need to be converted to
    • xx_Gn_XX_#####_blah
    using the following table:

    Values of #### xx
    00001 to 00099 FL
    00100 to 00199 IN
    00200 to 00299 NL

    This explains some of the forest of IF-THEN-ELSE logic that I built.

    The second line of the activity reads "Grade m, Unit n, Lesson o"; I parse m, n, & o out of it and append them to the file name.

    The first line of an activity is used to name the output file that the activity is inserted into and removed from the text being written to that file.

    Thanks,
    Ron
    Windermere, FL

  15. #55
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Is the second line always some form of "Grade m, Unit n, Lesson o"?

  16. #56
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Couple of quick notes:
    1. I can't easily step through your code to see how it all comes together, because you've got some very specific stuff tailored to you quite deep in the code (get_SrcDir, as a start)

    That kind of stuff is much more easily accomplished using constants (Public Const DIR_SOURCE as String = "C:\User\Ron\Desktop\Unit-Test\" -- and of course, you can just comment out one or the other constant at the top of the module to switch between testing vs the "live" function) at the top of the module, OR, to get the best of both worlds... use a constant at the top of the module, but leave the function call which utilizes the constant, until later where you use a userform/word native dialog to decide which directory structure you want to search and plop stuff in.

    2. I love the development of your use of functions. Just to keep pushing you in the right direction: remember that ByRef and ByVal can be useful, and that ByRef (in almost all cases) is the default. So the following function has a couple of issues:
    [vba]
    Function Assign_UnitNo(myStr As String, Unit As Long)
    If Unit < 10 Then
    myStr = myStr & "U0" & Unit
    Else
    myStr = myStr & "U" & Unit
    End If
    Assign_UnitNo = myStr
    End Function
    [/vba] a) without an explicit type, you don't know that Assign_UnitNo is supposed to return a string, and
    b) at the end of that function, myStr and the returned value of Assign_UnitNo with be exactly the same outside the routine as well. This can cause devilish issues in trouble-shooting code when things get more complex. Better to use a "leave it alone" approach where possible, so in this case you might be served to change your parameter to ByVal myStr as String, that way when you get back out of the function, you can see the "Before" and "After" of that function. It also allows you to step through and say-- whoops, I screwed that up, let me try again.

    The reason why I bring this up is because you're also going to need to apply the "leave it alone" concept to your ranges. That you continuously pass in ActiveDocument.Content as your range argument allows you to get away with something which will cause you problems: namely, redefining the range within the same routine which is returning a range based on the passed in range. Range.Duplicate is your friend in these scenarios. Also, dimensioning variables in these sub-routines is helpful-- not everything has to be a parameter. My revamped FindActivity will make that clear...

    3. Comment your code way way more, especially in your top routine. Get in the habit of commenting stuff you understand at the moment, not just the hard to remember stuff. Makes it easier to come back later and modify. Also makes it easier for outside eyes to divine your intent, rather than puzzle over what you're actually doing

    It looks like you're actually showing a dialog to get a path, and then you want to return the value of that path, and then you open a document based on a dialog you've shown. You may be able to just use the FileOpen (you can set default paths on that before opening) dialog to accomplish that, or you may be looking for something along the following code (change the optional parameter to false, to skip the whole messagebox thing):
    [vba]
    'Return a valid path from a dialog, or return an empty string
    Public Function fGetPathViaDialog(Optional bShowAMessageBox As Boolean = True) As String
    Dim sRet As String
    Dim oMyDialog As FileDialog

    'set our dialog to...
    Set oMyDialog = Application.FileDialog(msoFileDialogFolderPicker)

    'set some of the available custom properties (use locals window to see more)
    With oMyDialog
    'OK button
    .ButtonName = "Hello"
    'caption (top of the dialog)
    .Title = "Find my stuff"
    'if you allow this, the selected items may have more than 1
    .AllowMultiSelect = False
    .InitialFileName = "C:\Users\"

    'show it
    .Show
    'return the string (notice that it takes off the end "\"), if the user didn't hit cancel
    If .SelectedItems.Count > 0 Then
    sRet = .SelectedItems(1)
    End If
    End With

    'messagebox it?
    If bShowAMessageBox Then
    If sRet = "" Then
    MsgBox "You hit cancel!"
    Else
    MsgBox "You chose:" & vbCr & sRet
    End If
    End If

    'and don't forget to actually have the function return the value
    fGetPathViaDialog = sRet
    End Function
    [/vba] Or maybe something as simple as...
    [vba]Public Sub OpenADocument(Optional sSuggestedPath As String)
    With Dialogs(wdDialogFileOpen)
    'can use this instead of changing Global.ChangeFileOpenDirectory
    .Name = sSuggestedPath
    'use this to display the dialog
    .Show
    'can use this to automatically open the file of the suggested path
    '.Execute
    End With
    End Sub
    [/vba]
    A new FindActivity coming shortly... got sidetracked. Obviously. The reason I didn't answer your question directly is because I think the methodology of trying to find the "end" of a section is flawed, if everyone is ending the section differently.

    The "Start" of the section is going to be more standard (or this entire process breaks, since you're extracting data from specific strings in a specific way), so probably better to figure out a robust way of identifying that.
    Last edited by Frosty; 04-29-2011 at 05:07 PM.

  17. #57
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Does this wildcard search yield the "first" line of each unit? Wildcard searches can be really useful.

    [vba]
    Sub QuickWildCardTest
    Selection.Find.ClearFormatting
    With Selection.Find
    .Text = "??_[Gg]?_??_"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindContinue
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchAllWordForms = False
    .MatchSoundsLike = False
    .MatchWildcards = True
    End With
    Selection.Find.Execute
    End Sub
    [/vba] Basically I'm looking for the underscore character, with a specific number of characters between the instances, as well as the "g"... if that's enough criteria to always identify the text in that first paragraph, you can expand that found range nicely. But without all of your samples, it can be a little tricky.

    And, I believe, using wildcard searches can have some potential issues (such as corrupting the find object on an unsuccessful search), but there are some standard practices to avoid that. Let me know if this looks promising, and I can help point you further in the right direction.

  18. #58
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    This was the link I forgot to provide:
    http://word.mvps.org/faqs/General/UsingWildcards.htm

    great great info on using the wildcard search functionality... and by extension, doing some pretty extensive coding based on it.

  19. #59
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Quote Originally Posted by Frosty
    Is the second line always some form of "Grade m, Unit n, Lesson o"?
    Yes.

    Thank you for your excessive critique and guidance on improving my coding; and a big Thank You for the encouragement.

    I've been out sick and busy with work over the past month or so. I'll pour over and ponder your advice and return with questions over the next week or so. I'm entertaining family from the West/Left coast for the next several days.

    Thanks,

    Ron
    Ron
    Windermere, FL

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •