Consulting

Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 21 to 40 of 59

Thread: Splitting a document into multiple documents

  1. #21
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Sure thing! Hope it helps, and look forward to seeing the next bits

  2. #22
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Me, too. I'm anxious to dig into this but first I need to complete and deliver a project by BoB on Monday. So, back it's to on the clock.
    Ron
    Windermere, FL

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

    How do we avoid using Activate to change which file I'm reading from, writing to, or closing? By having the function or subroutine open the file immediately before I read or write using it?

    When do I cut/delete the information that I've moved into rngActivity.select (you called it rngLesson)?

    Here is your code updated for the notes in your two followup messages. Do I have this right? (as above, I changed references from Lesson to Activity)

    [VBA] 'selecting always helps when working with ranges
    Sub SelectMyActivity()
    Dim rngSearch As Range
    Dim rngActivity As Range
    Set rngSearch = ActiveDocument.Content
    Set rngActivity = FindMyActivity(rngSearch)
    'find it and select it
    rngActivity.Select

    End Sub

    'returns an expanded range, selecting the entire document if page break not found
    Function FindMyActivity(rngLookWhere As Range) As Range
    Dim lStart As Long
    lStart = rngLookWhere.start
    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
    rngLookWhere.start = lStart
    LastActivity = False
    Else
    Set rngLookWhere = ActiveDocument.Content
    LastActivity = True
    End If
    End With
    Set FindMyActivity = rngLookWhere
    End Function
    [/VBA]

    Thanks,
    Ron
    Windermere, FL

  4. #24
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Instead of using ActiveDocument, start setting variables to the particular documents.

    Dim oDocSource as Document
    dim oDocNew as Document

    Set oDocSource = ActiveDocument when you start...

    Then as you search the range of that oDocSource (oDocSource.Content) to get your activities, you create new documents (Set oDocNew = Documents.Add())

    As you save and close the oDocNew, you can set it to another new document.

    You only need to .Select these ranges as you're stepping through the code in order to understand whether you're finding the right range. And you only need to activate the particular document variables to make sure you're getting info from your source document, and putting info into your recently created document.

    At the end of the day, there is no reason to to select ranges or activate documents... computers don't need to turn the lights on to do their work. Only humans do.

    Make sense?

  5. #25
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Sorry, a little quick with my response.

    1) What is the LastActivity variable, and why do you need it? If you need it, then you should probably do something with it (as well as declare it-- you are using "Option Explicit" at the top of all of your modules, right?)

    2) At some point you will translate this code into something like...
    (warning: this is pseudo code)
    [vba]
    Set oDocSource = ActiveDocument
    'loop through all of the activities in your source document
    Do
    'get the activity
    set rngActivity = FindMyActivity(oDocSource.Content)
    'do a bunch of stuff with your activity (splitting into separate testable routines)
    rngActivity.Copy
    'create your new activity document
    set oDocNew = Documents.Add
    oDocNew.Paste
    oDocNew.Save '(with whatever naming parameters you've done above)
    oDocNew.Close
    'loop until my search returned the last activity in my source document
    Loop Until rngActivity = oDocSource.Content
    [/vba]

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

    Thanks, setting Document variables to makes sense.

    What still puzzles me is at what point to I .cut the range I've found from the source document so when I return to it, it's 'top' is now just below the most recently found "My Notes:" instance?

    When rngLookWhere = ActiveDocument.content (because there is no trailing ^m) how does the program know that I'm done with that Source file and it's time to iterate the Unit number? I decided to add the flag LastActivity and flip it from False to True. I have in mind using it in the calling routine to control a loop.

    Whoops! I see: Loop Until rngActivity = oDocSource.Content


    Thanks,
    Ron
    Windermere, FL

  7. #27
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    There are many ways to do this, so don't take my suggestion as the "right" way... I just happen to be the one responding.

    You can .Cut the material to continue shortening your source file... and then ultimately you can close the source file without saving changes. I'm not a fan of this approach, because I don't like modifying "source data" in general.

    But you can also modify your range each time. Remember that ranges are primarily defined by their .Start and .End property (at the simplest level). So the first "Activity" in your source document will be something like rngActivity.Start = 0 and rngActivity.End = 1254.

    So as you move through your source document... keep changing the .Start value of your RngSearch to the End of your rngActivity value.

    You may need to change your logic so that then your FindMyActivity function doesn't return the rngSearch.Parent.Content when it doesn't find a page break (preferable to ActiveDocument.Content in this context), but rather returns a range which starts with rngSearch.Start and ends with rngSearch.Parent.Content.End. This approach would allow you not to modify your source document at all.

    While you're playing with this... it's going to be helpful to keep going through the little chunks. Figure out how to iterate through your source document the right number of times, identifying the correct ranges each time (just .Select it and show a message box as your proof of concept).

    Once you've got the (pseudo code) For Each MyLesson in oMyDoc.Activities part worked out... then it's time to sort out how to play with a specific range (activity). And all you have to do is write that code to deal with a passed in range. As you play with that code, you just manually select the activity (since you already know how to do that), and start extracting the bits from there by using the immediate window:
    GetInfoFromMyActivityRange Selection.Range, "Lesson Name"

    And that looks something like (there are so many variations to this, this is just the first one I thought of:
    [VBA]
    Public Function GetInfoFromMyActivityRange (rngActivity as Range, sInfoWhat as String) as String
    Dim sRet as string
    Select Case sInfoWhat
    Case "Lesson Name"
    sRet = rngActivity.Paragraphs(1).Range.Text
    Case Else
    sRet = "I dunno!"
    End Select
    GetInfoFromMyActivityRange = sRet
    End Function
    [/VBA]

    That's what I mean by breakable chunks. You're mixing and matching your tasks when you ask me a question about iterating the unit number in the context of being "done" with the source file.

    First... find your first activity.
    Then... figure out how to just loop through each activity in your document and stop at the end (which is not just a learning experience, but a decision: how do you want to handle your source document?)
    Then... figure out how to deal with your individual activities (and what information is contained in them).

    It becomes much easier when you are correctly identifying your own tasks. Experience will help in that identification, so that is part of the lesson.

  8. #28
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    It really does help not to necessarily think linearly when designing these kinds of approaches... just because you're going to find your first lesson, get info about your first lesson, create a new document based on your first lesson, put some stuff in that new document based on your first lesson, go to your second lesson... doesn't mean you should code it that way.

    Invariably, if you code in a linear fashion... you find out you're screwed when you get to your last lesson... because there are no more page breaks. Grin.

    Much better to figure out how to find all of your lessons in any way you choose... and then move on to getting whatever info you want about a particular lesson. Etc etc.

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

    I'm looking at my "problem" of needing to get my 2nd activity into the file with the first one, all without resorting to GOTO branches.

    One solution is to close the output file after adding an Activity to it. Then, as I process my "header info" in the next activity, I open the new filename to see if it already exists, if it is the 2nd or subsequent Activity for a Lesson it will, else the error will tell me to create a new document/file. How easy is it to trap and use the file open error (no file by that name) in IF/THEN/ELSE logic?

    That Loop Unit rngActivity = oDocSource.Content looks like it might be a problem. If I delete the Activity from the oDocSource as I paste it into oDocNew when I (or my program) does this test oDocSource will be empty and <> rngActivity. Am I wrong?

    Thanks,
    Ron
    Windermere, FL

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

    Thanks for the extended advise. I'll stop and work on the bits, one at a time to learn more about what I have. If I go with the technique of deleting the activities as I paste them, the deletion will be from a copy of the source file, not the file itself. But, I like the idea of moving the start and end pointers, that will work much better and cutdown on file reads and writes which are time-consuming, relatively speaking.

    First, I believe that I'll sleep on this overnight.

    Thanks,

    Ron
    Ron
    Windermere, FL

  11. #31
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    Couple quick responses:
    1) don't worry too much about optimizing your code to get better "speed" in VBA. Once you stop using the Selection object (i.e., you program correctly), the benefits of code optimization are marginal, for the most part. There are exceptions to this (like everything), but they are pretty small, at least from what I'm looking at in your task list here. If you were processing tens of thousands of excel rows and writing them to table cells, it might be different.

    2) Sleep is good

    3) I sound full of myself at times... take it with a grain of salt. I'm trying to help you without doing it all for you, but I'm actually not as pompous as I sound. Grin.

    It sounds like you're getting a little overwhelmed/mentally stuck by the whole looping through multiple activities and what to do with your source document, etc.

    Tell you what. Work out your process for just dealing with a selected Activity and getting whatever info you need from the selected lesson into a totally new document, and saving that document as the "right" name.

    Just make sure your process works for whatever activity in the source document you've selected. Don't worry about whether you copy or cut the info, just get the info you need and put it in a new document.

    Checking to see if the file already exists and looping through all the activities is easy... and I'll be able to give you a really good code sample if I see the nitty-gritty (code which works for any type of activity).

    This is an interesting little problem, and I'm hoping to help. At the same time, if I find some time next week, I can probably just give you the whole thing... but it depends on whether you're interested in just getting it done or learning all the available lessons in this relatively complex process.

  12. #32
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    There are trade-offs, I'd rather learn as many lessons as I can but on the other hand at some point I have to have processed the 56 files and shipped the "lesson" files to another department in the company. There are some other priorities on the list for early this week, so, I'll have time to work on learning.

    Thanks, again.
    Ron
    Windermere, FL

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

    After reopening a file and doing .MoveEnd, how do I get VBE to allow me to insert my next Activity after the one in the file? Here's a code fragement:
    [vba]Sub A_Fragment()
    If myOutFile <> LastFileName Then
    Set oDocNew = Documents.Add
    Else
    Call Open_File(myOutFile, ".rtf", SrcDir)
    Set oDocNew = ActiveDocument
    oDocNew.Content.MoveEnd
    End If
    oDocNew.Paste ' <<< how do I InsertAfter instead of Paste over?
    End Sub
    [/vba]

    Thanks,
    Ron
    Windermere, FL

  14. #34
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    .Content is just a description of the range of the entire MainStory of the document. You can't .MoveEnd on that.

    Also... just to clarify the concept... the .End of the range is the, well.. the end... so you would want to .MoveStart if you want to insert after (even though that wouldn't work either on the .Content object either).

    What you can do is (pseudo code):
    Set myRange = oDocNew.Content
    myrange.Collapse wdcollapseend
    myrange.paste (does paste work off the range object?)

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

    Yes, Paste is a method of the Range object.

    I was about to ask you about how to display the FileOpen dialog but I noticed your Dialogs answer to another user and that sent me to Dialogs in Help, so, I have that answer, now.

    Can I use that (FileOpen) dialog to pick and then set a starting directory location?

    The matter of pasting a second activity into the RTF file that already has one activity is still a challenge. As in, it's still not working. I'm letting that sit for a moment while I test and debug some other stuff.

    Cheers!
    Ron
    Windermere, FL

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

    Is there a way to get the wdDialogFileOpen to tell me what directory is chosen, whether or not I open a file at the same invocation of the dialog?

    [vba]Sub ShowOpenDialog()
    Dim dlgAnswer As String
    dlgAnswer = Dialogs(wdDialogFileOpen).Show
    ' Return value Description
    ' -2 The Close button.
    ' -1 The OK button.
    ' 0 (zero) The Cancel button.
    ' > 0 (zero) A command button: 1 is the first button, 2 is the second button, and so on.
    End Sub
    [/vba]
    The return values tell me a little bit but leave me wondering what file I opened and what directory it was in. Since that file is now the ActiveDocument, I can use the Name and Path properties IF/WHEN I open a file. But, if all I do is use the dialog to change directories, I'm a bit adrift.

    Thanks,
    Ron
    Windermere, FL

  17. #37
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    The dialogs collection is pretty under-documented.

    Check this out:
    http://word.mvps.org/faqs/macrosvba/BrowsDialog.htm

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

    I pulled the several downloads mentioned in the article and made a PDF of the article, itself.

    Cheers,
    Ron
    Windermere, FL

  19. #39
    VBAX Expert
    Joined
    Aug 2007
    Location
    Windermere, FL, a 'burb in the greater Orlando metro area.
    Posts
    567
    Location
    Jason, et al,

    Apparently, the only remaining issue is that of getting the 2nd Activity's FormattedText inserted into oDocNew after the existing text. Here is the relevant block of code from my program. My challenge is in the Else block, when I run the code, the only thing added to oDocNew is a Paragraph mark (symbol) which I interprete as meaning that I succeeded in inserting a CrLf.

    What should the target document (oDocNew) look like after the line rngDocNew.Collapse Direction:=wdCollapseEnd is executed? When I change to that window, how should my document appear? For instance, when I select an Activity, it is highlighted in the source doc window.
    [vba] Do Until ActivityEnd = oDocSource.Content.End
    Call Find_MyActivity2(oDocSource.Content, rngActivity, ActivityStart, ActivityEnd)
    'find it and select it
    myOutFile = Get_MyOutFile(rngActivity)
    rngActivity.Select
    rngActivity.Copy
    oDocScrap.Range.Paste
    Set rngScrap = oDocScrap.Content
    Set rngScrap = Delete_1stLine(rngScrap)
    rngScrap.Select
    rngScrap.Cut
    ' If myOutFile = LastFileName Then
    ' myOutFile = myOutFile & "a"
    ' End If
    If myOutFile <> LastFileName Then
    Set oDocNew = Documents.Add
    oDocNew.Range.Paste
    Else
    ' Debug.Print myOutFile
    ' Stop
    Call Open_File(myOutFile, "MyOutFile", "", SrcDir)
    Set oDocNew = ActiveDocument
    Dim rngDocNew As Range
    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
    Loop
    [/vba]

    Thanks in advance for your assistance.

    Cheers,
    Ron
    Windermere, FL

  20. #40
    VBAX Master
    Joined
    Feb 2011
    Posts
    1,480
    Location
    I might need to see more than the do loop to help you clean it up a bit. But it's looking like you're really separating things out well. Couple of comments before I answer your question (of course, you can just skip to the end too, grin).

    1. Open_File is a subroutine? Why not make it a function which returns the document it opens? Then you can...
    set oDocNew = Open_File(myOutFile, "MyOutFile", "", SrcDir)

    2. It looks to me like you would benefit from using the Optional Parameter (no reason to pass in "" as an argument into a proc you've developed)

    3. FindMyActivity2... I'm a little confused by your parameters there... why are you passing a range, and what looks to be the start and the end of that range? I assume it's because you're only *really* passing in the activedocument.content range... and then returning the rngActivity as a return value... but you don't need to return start and end-- they come along as properties of your rngActivity.

    4. This is somewhat of a preference thing-- but putting Dims in the middle of your routines can make it harder to troubleshoot later. The good news about this comment is that once we're getting into stylistic type stuff, you know you're getting close on the actual coding.

    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.

    However, I do take exception to your naming convention here... you don't want to call it rngDocNew... you want to call it rngInsertHere (or something similar).

    I make that point because, even without being able to see the rest of your code, your naming convention was pretty much good enough for me to get an idea of what was going on-- which is fantastic.

    One other point: You do not need to .select a range to work with it... but it is helpful when you're stepping through your code to type rngScrap.Select in the immediate window at any given point to see what you're actually working with. However, you can probably get rid of every line of code in which you use .Select (and you should see if you can get rid of every line of code which uses ActiveDocument, and instead try to pass the document object around).

    Looking good, Ron. I would love to see your code project at the end... I might be able to do a quick sweep through and give you some last coding style pointers (without slowing down the actual need to get the project out the door).

    - Jason

Posting Permissions

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