Results 1 to 13 of 13
  1. #1
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I am using MS Word Version 2003. I need to automate an activity wherein there are chunks of code in an API document known as function prototypes. These protoypes need to be compared with the code given in the document containing all the header files so that it points out the differences in the API document.

    The sequence of prototypes in the API document and the document containing all the header files is also not the same.

    The folllowing is the structure of a sample function prototype:
    AAA_XXX_CXXX TxssssssRes (
    IN Aaaaaaaaa_t * ptrTtttt,
    IN Bbbbbbbbbb_t hhh,
    IN Cccccccccc_t shhh,
    IN Dddddddddd_t dddId
    );
    I am looking for a macro that can perform the following steps:
    • Select the name of the function from the function prototype (given in bold in the sample function prototype).
    • Search the function in the document containing all the header files.
    • Compare the two chunks of code given in the document containing all the header files and the API document.
    • Point out the differences in the code given in the API document (same way as we get the differences when we compare two word documents.

    Please note that an API document would not just have code but some other sections such as, the description of the prototype. One pointer is that the function prototypes are always represented by the "code para" style in the API document.

    We know that the "search" and "compare" features are there in MS Word, however, I am not sure about how to use those features for creating a macro to completely or partially automate this activity.

  2. #2
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    Just to take on the first little piece of this: it should be easy enough to take a (user-selected?) function name and save it into a string, and then use that string to search for a match in the second document. But in order to do document compares on the full chunks of the prototype code from both documents, there needs to be a way for the (VBA) code to expand from the selected/found function names in the two documents, to grab each entire respective chunk of prototype code (so that each chunk could be saved into a separate new document, and a document compare then run between the two docs).

    Is there a consistent pattern in the chunks of prototype code, that could be used for the VBA code to expand out from the function name, to capture the entire prototype chunk? If each prototype code chunk ends in a semicolon, you can expand the selection/range to the semicolon at the end, but is there any similar consistent pattern that could be used to expand the range to the start of the prototype chunk? - are there a set number of characters that exist to the left of the function name, or any other similar reliable feature that could be used?

    Gary

  3. #3
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    [quote name='Gary Frieder' post='794122' date='20-Sep-2009 03:21']Just to take on the first little piece of this: it should be easy enough to take a (user-selected?) function name and save it into a string, and then use that string to search for a match in the second document. But in order to do document compares on the full chunks of the prototype code from both documents, there needs to be a way for the (VBA) code to expand from the selected/found function names in the two documents, to grab each entire respective chunk of prototype code (so that each chunk could be saved into a separate new document, and a document compare then run between the two docs).

    Is there a consistent pattern in the chunks of prototype code, that could be used for the VBA code to expand out from the function name, to capture the entire prototype chunk? If each prototype code chunk ends in a semicolon, you can expand the selection/range to the semicolon at the end, but is there any similar consistent pattern that could be used to expand the range to the start of the prototype chunk? - are there a set number of characters that exist to the left of the function name, or any other similar reliable feature that could be used?

    Gary[/quote]

    Hi, Thank you for a quick response. There might not be a fixed number of characters before the function name, however, the name of the function is always followed by an opening brace "(" or "{". I basically need to compare the content between the starting brace and the closing brace in the API document and in the document containing the header files with the name of the function as a unique identifier for that particular function prototype. In addition, the name of the function is generally the second word of the function prototype. The first word might contain any number of characters.

    Ricky

  4. #4
    Super Moderator jscher2000's Avatar
    Join Date
    Feb 2001
    Location
    Silicon Valley, USA
    Posts
    23,112
    Thanks
    5
    Thanked 93 Times in 89 Posts
    I have no idea how to code the logic to make the comparison. If you dump the snippets out to files, you could use Word's comparison engine or a third party component to compare them, but that doesn't seem very efficient...

  5. #5
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    [quote name='Ricky' post='794131' date='20-Sep-2009 05:59']Hi, Thank you for a quick response. There might not be a fixed number of characters before the function name, however, the name of the function is always followed by an opening brace "(" or "{". I basically need to compare the content between the starting brace and the closing brace in the API document and in the document containing the header files with the name of the function as a unique identifier for that particular function prototype. In addition, the name of the function is generally the second word of the function prototype. The first word might contain any number of characters.

    Ricky[/quote]
    If the functions begin and end with braces, those could be used to identify the chunks of text to grab, but before we go there, just to follow up on Jefferson's question: How many of these functions do you need to compare, and how automated does the process need to be?

    The outline sketched in my previous post might be workable if you just need to compare one specific function with the equivalent one in the second document. But if the number of functions to be compared number in the dozens, or hundreds, then the approach of dumping the code chunks into pairs of new documents and running compares between those, is going to get very unwieldy fast.

    Gary

  6. #6
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    [quote name='Gary Frieder' post='794202' date='21-Sep-2009 00:43']If the functions begin and end with braces, those could be used to identify the chunks of text to grab, but before we go there, just to follow up on Jefferson's question: How many of these functions do you need to compare, and how automated does the process need to be?

    The outline sketched in my previous post might be workable if you just need to compare one specific function with the equivalent one in the second document. But if the number of functions to be compared number in the dozens, or hundreds, then the approach of dumping the code chunks into pairs of new documents and running compares between those, is going to get very unwieldy fast.

    Gary[/quote]
    Hi Gary,

    The number of functions can vary according to the API document to be validated. However, the number of functions will always be close to 100 in a document. But if we can create a macro to be used for just one function, we can reuse that macro for the rest of the functions in the API document. It will still be like 100 mouse clicks for an API document. It will still be much better than comparing and validating each and every parameter manuallly against the header file. Thanks for your response.

    Regards,
    Ricky.

  7. #7
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    [quote name='Ricky' post='794282' date='21-Sep-2009 11:08']Hi Gary,

    The number of functions can vary according to the API document to be validated. However, the number of functions will always be close to 100 in a document. But if we can create a macro to be used for just one function, we can reuse that macro for the rest of the functions in the API document. It will still be like 100 mouse clicks for an API document. It will still be much better than comparing and validating each and every parameter manuallly against the header file. Thanks for your response.

    Regards,
    Ricky.[/quote]
    Ricky,

    Here's the beginning of some workable code. Have just finished a 12-hour shift(!) and need to get to sleep, so have cut a number of corners here, just to get something that at least functions.

    For now, the code assumes you've got two documents, called "HeaderFilesDoc.doc", and "APIDoc.doc", and they are both in a folder called "C:\Test"
    The code assumes the user has got HeaderFilesDoc.doc open, and has selected the function name.
    The code also assumes that there's another folder called "C:\Scratch" into which scratch files can be saved (the code should also take care of killing scratch files once they're done with, but have not included that either, for now).
    The code assumes that the function code chunks start and end with regular parentheses aka 'curly quotes' - this could also be amended to accept either these or brackets/braces.
    The code would need to be in a global add-in template, or for quick testing purposes, you can put it into Normal.dot.
    The code currently does not contain error handling that it would need for real use.

    It's passed a quick test here; let me know how this works for you.
    (By the way, this was done using Word 2002; it should work OK in Word 2003.)

    [Edited to correct line of search code that contained a hard-coded string, rather than variable]

    Gary
    Code:
    Public Sub CompareProcedureCode()
    
       'This code would go into a global add-in template
       Dim HeaderFilesDoc As Document
       Dim APIDoc As Document
       Dim TmpDoc1 As Document
       Dim TmpDoc2 As Document
       Dim strFunctionSig As String
       Dim HeaderFilesDocFunctionText As String
       Dim APIFileDocFunctionText As String
       Dim strTmpDoc2Name As String
       
       Application.ScreenUpdating = False
       
       'Assumes we are starting out with HeaderFilesDoc open:
       Set HeaderFilesDoc = ActiveDocument
       
       strFunctionSig = Selection.Text
       If Len(strFunctionSig) = 0 Then
    	  MsgBox "Must select text before running this procedure!"
    	  Set HeaderFilesDoc = Nothing
    	  Exit Sub
       End If
       
       Selection.Extend ")"
       HeaderFilesDocFunctionText = Selection.Text
       
       Set TmpDoc1 = Documents.Add
       TmpDoc1.Content = HeaderFilesDocFunctionText
       
       'No longer need the Header Files document open:
       HeaderFilesDoc.Close wdDoNotSaveChanges
       
       'For expediency, am hard-coding name - should add dialog to browse to doc
       Set APIDoc = Documents.Open("C:\Test\APIDoc.doc")
       
       With APIDoc.Content.Find
    	  .ClearFormatting
    	  .Text = strFunctionSig
    	  .Replacement.Text = ""
    	  .Forward = True
    	  .Wrap = wdFindStop
    	  .Format = False
    	  .MatchCase = False
    	  .MatchWholeWord = False
    	  .MatchWildcards = False
    	  .MatchSoundsLike = False
    	  .MatchAllWordForms = False
    	  .Execute
       End With
       
    	'For expedience right now, am assuming there will be a match
       Selection.Extend ")"
       APIFileDocFunctionText = Selection.Text
       
       Set TmpDoc2 = Documents.Add
       TmpDoc2.Content = APIFileDocFunctionText
       TmpDoc2.SaveAs "C:\Scratch\TmpDoc2.doc"
       strTmpDoc2Name = TmpDoc2.FullName
       
       'No longer need the API File document open:
       APIDoc.Close wdDoNotSaveChanges
       
       TmpDoc1.Compare Name:=strTmpDoc2Name, CompareTarget:=wdCompareTargetNew
       
       TmpDoc1.Close wdDoNotSaveChanges
       TmpDoc2.Close wdDoNotSaveChanges
       
       Set TmpDoc1 = Nothing
       Set TmpDoc2 = Nothing
       Set HeaderFilesDoc = Nothing
       Set APIDoc = Nothing
       
       Application.ScreenUpdating = True
    
    End Sub

  8. #8
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi Gary,

    Thank you for the code and really sorry for the late response, the macro is not giving any error messages, however, the objective of the macro is to point out the text in the chunk of code that is there in the headerfile.doc but not in the API.doc in a specific colour that is different from the rest of the text (the text that exists in the headerfile.doc as well as in API.doc). Similarly, it should also be able to point out the the text in the chunk of code that is there in the API.doc but not in the headerfile.doc (it can be displayed as a text in different colour or deleted text).

    Currently, it is not pointing out the differences in different colour and it also inserts some junk text in the new document that is displayed as deleted text (looks like the table of contents of the API document with the section number).

    In addition, there are few more modifications that are required in the macro:
    • The active document must be API.doc and not headerfile.doc from where the name of the function is supposed to be selected.
    • As the number of functions can be more than 100 in a document which need to be compared (as we are validating them individually), the API document must not be closed after running the macro because of which we will be required to open the document again and again.

      An example of the output is given below:
      AAA_XXX_CXXX TxssssssRes (
      IN Aaaaaaaaa_t * ptrTtttt, //text present in headerfile.doc but not in API.doc
      IN Bbbbbbbbbb_t hhh,
      IN Cccccccccc_t shhh,
      IN Dddddddddd_t dddId);// marked as deleted text, text present in API.doc but not in headerfile.doc

  9. #9
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    [quote name='Ricky' post='797544' date='12-Oct-2009 13:50']Hi Gary,

    Thank you for the code and really sorry for the late response, the macro is not giving any error messages, however, the objective of the macro is to point out the text in the chunk of code that is there in the headerfile.doc but not in the API.doc in a specific colour that is different from the rest of the text (the text that exists in the headerfile.doc as well as in API.doc). Similarly, it should also be able to point out the the text in the chunk of code that is there in the API.doc but not in the headerfile.doc (it can be displayed as a text in different colour or deleted text).

    Currently, it is not pointing out the differences in different colour and it also inserts some junk text in the new document that is displayed as deleted text (looks like the table of contents of the API document with the section number).

    In addition, there are few more modifications that are required in the macro:
    • The active document must be API.doc and not headerfile.doc from where the name of the function is supposed to be selected.
    • As the number of functions can be more than 100 in a document which need to be compared (as we are validating them individually), the API document must not be closed after running the macro because of which we will be required to open the document again and again.

      An example of the output is given below:
      AAA_XXX_CXXX TxssssssRes (
      IN Aaaaaaaaa_t * ptrTtttt, //text present in headerfile.doc but not in API.doc
      IN Bbbbbbbbbb_t hhh,
      IN Cccccccccc_t shhh,
      IN Dddddddddd_t dddId);// marked as deleted text, text present in API.doc but not in headerfile.doc
    [/quote]
    Hi again,

    Your initial post only gives one example of a sample function prototype, so that's all we have to work with in coming up with some code - the code I posted seems to work fine on that one example. Without seeing a more extended sample - including examples that are giving trouble - there's no meaningful way to troubleshoot the code to address these - can you post an (abridged) pair of sample documents, that could be used to test further?

    As far as the different colors not always being reliable, hard to tell what's going on without a wider sample, but just as a general observation, Word's internal compare documents feature isn't always the most reliable thing going (that's why third-party tools like CompareRite, and more recently DeltaView/Workshare Compare, control the market in applications where accuracy is paramount), but it's the only option that's available for a quick-and-dirty solution such as can be tailored here. If you had an application like Workshare Compare, you might be able to have a Word macro that somehow sorts the two documents to be compared, so that the order of the functions is the same in both documents - that would then allow you to use the third-party tool to get a reliable comparison.

    As far as the active doc needing to be API doc, and not the other way around, that's easily adjusted - you could even modify the code yourself: simply switch around all references in the code to "HeaderFilesDoc" and "APIDoc".

    As far as keeping the API doc open after the comparison is run, the way Word's compare documents feature works, it's going to automatically close the initial document that the comparison is run from, leaving you with only the resultant comparison document open. It would be possible to work around that in the code, by having the code capture the filename and path of the API doc at the beginning, and then using that to reopen the API doc, after the remainder of the procedure has run.

    Gary

  10. #10
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi Gary,


    I have attached the sample API and headerfile docs with this post. It is giving the desired results for the first two functions TxssssssRes and TxssssssRes1 listed in these documents. However, it is not giving the same results for the last function name TxssssssRes2 mentioned in these documents. The result documents have also been attached with the post.


    These results are valid if the APIs in the header file and in the APIs are in the same sequence, however, if they are not in the same sequence i am also attaching the document to demonstrate the results. The document to demonstrate that is named as "Not_in_same_sequence".


    The APIs in the header file and in the API document would never be in the same sequence. Please try to run the macro in all the different situations and suggest a solution.

    Regards,
    Ricky.
    Attached Files Attached Files

  11. #11
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    [quote name='Ricky' post='798750' date='19-Oct-2009 07:32']Hi Gary,


    I have attached the sample API and headerfile docs with this post. It is giving the desired results for the first two functions TxssssssRes and TxssssssRes1 listed in these documents. However, it is not giving the same results for the last function name TxssssssRes2 mentioned in these documents. The result documents have also been attached with the post.


    These results are valid if the APIs in the header file and in the APIs are in the same sequence, however, if they are not in the same sequence i am also attaching the document to demonstrate the results. The document to demonstrate that is named as "Not_in_same_sequence".


    The APIs in the header file and in the API document would never be in the same sequence. Please try to run the macro in all the different situations and suggest a solution.

    Regards,
    Ricky.[/quote]
    Hi Ricky,

    Just back after a day offline. Will try to look at the code again later today. In the meantime, it still seems to me that the whole project would be much simpler if you could compare the two documents with the API codes being in the same order - if you did this, you wouldn't even need any VBA code, you could just directly compare them using Word's compare documents feature.

    Since each API text block is one paragraph (with text going to new lines with line breaks) it seems that you should readily be able to sort these documents (to put the APIs in the same order), before comparing them.
    Have you tried the following?:
    Make copies of each document to be compared. For each copy document, open it, Ctrl+A to select all, then go to Table > Sort. If you do this in both documents, it should put the API text in the same order in both documents. Then you could use Word's document compare feature (Tools > Compare and Merge Documents) to generate a comparison.

    Not only would this be much faster than writing a lot of custom code (which may or may not arrive at a solution in this case), but this would also have the benefit that you'd end up with a single comparison document - rather than having a separate comparison document created for each text chunk.

    Gary

  12. #12
    New Lounger
    Join Date
    Sep 2009
    Posts
    8
    Thanks
    0
    Thanked 0 Times in 0 Posts
    [quote name='Gary Frieder' post='799036' date='20-Oct-2009 12:02']Hi Ricky,

    Just back after a day offline. Will try to look at the code again later today. In the meantime, it still seems to me that the whole project would be much simpler if you could compare the two documents with the API codes being in the same order - if you did this, you wouldn't even need any VBA code, you could just directly compare them using Word's compare documents feature.

    Since each API text block is one paragraph (with text going to new lines with line breaks) it seems that you should readily be able to sort these documents (to put the APIs in the same order), before comparing them.
    Have you tried the following?:
    Make copies of each document to be compared. For each copy document, open it, Ctrl+A to select all, then go to Table > Sort. If you do this in both documents, it should put the API text in the same order in both documents. Then you could use Word's document compare feature (Tools > Compare and Merge Documents) to generate a comparison.

    Not only would this be much faster than writing a lot of custom code (which may or may not arrive at a solution in this case), but this would also have the benefit that you'd end up with a single comparison document - rather than having a separate comparison document created for each text chunk.

    Gary[/quote]

    Hi Gary,

    I have tried the suggestion given by you, however the code given in the header file is always much more than in the API document (even though we select all the code from the API and paste it to a different document). Even if we sort it it, we would not be able to compare the codes in the two documents.

    The code given by you is working in some cases but needs some modifications in it, such as , the function names in the header files document and the API document would never be in the same sequence and it is sometimes not giving the desired results even though the function names in both the documents are in the same sequence. I have attached all the files with my previous post to troubleshoot the different scenarios. Looking forward to your response.

    Regards,
    Ricky

  13. #13
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts
    [quote name='Ricky' post='799322' date='22-Oct-2009 05:43']Hi Gary,

    I have tried the suggestion given by you, however the code given in the header file is always much more than in the API document (even though we select all the code from the API and paste it to a different document). Even if we sort it it, we would not be able to compare the codes in the two documents.

    The code given by you is working in some cases but needs some modifications in it, such as , the function names in the header files document and the API document would never be in the same sequence and it is sometimes not giving the desired results even though the function names in both the documents are in the same sequence. I have attached all the files with my previous post to troubleshoot the different scenarios. Looking forward to your response.

    Regards,
    Ricky[/quote]
    Hi Ricky,

    Here's some further revised code. It seems to be working when tested here. Please note:

    As discussed earlier in this thread, this code is only meant to run on one function code chunk at a time - that is, for each function code chunk that you want to compare, you need to have the API doc open, and manually select the bolded function signature, then run the macro. You'll end up with two documents open: (1) the original API Doc; (2) a generated comparison document, showing differences between the function code in the API doc versus the Header File doc. You will need to repeat this procedure for each separate function code chunk to be compared.

    Per your comment, I've reversed the order of documents so that you now start with the API document open.
    Do not put this code into either the API doc or the Header file doc; it must either be in a global add-in template, or else in Normal.dot.
    If there is no match found in the Header file doc, you will get a message box saying no match found.

    When tested here, it works the same, no matter the order of the different function code chunks in the different documents. In order to make the test results clearer, I inserted obvious characters like "zzz" and "xxxx" into line of text in the Header file doc.
    Due to a limitation of Word's compare feature, it isn't granular enough to highlight individual characters changed in each line; rather, it shows any changed line as a complete replace (i.e. marked as insertion/deletion).
    Let me know if this gets closer to working for you now.

    [codebox]Public Sub CompareProcedureCode()
    'Gary Frieder - Woody's Lounge 10/23/2009
    'This code would go into a global add-in template
    'or Normal.dot - do not put this code into either of the
    'API or HeaderFiles documents!

    Dim HeaderFilesDoc As Document
    Dim APIDoc As Document
    Dim TmpDoc1 As Document
    Dim TmpDoc2 As Document
    Dim strFunctionSig As String
    Dim HeaderFilesDocFunctionText As String
    Dim APIFileDocFunctionText As String
    Dim APIFilePath As String
    Dim strTmpDoc2Name As String
    Dim fMatch As Boolean

    Application.ScreenUpdating = False

    'Assumes we are starting out with APIDoc open:
    Set APIDoc = ActiveDocument

    strFunctionSig = Selection.Text
    If Len(strFunctionSig) = 0 Then
    MsgBox "Must select text before running this procedure!"
    Set APIDoc = Nothing
    Exit Sub
    End If

    Selection.Extend ")"
    APIFileDocFunctionText = Selection.Text

    Set TmpDoc1 = Documents.Add
    TmpDoc1.Content = APIFileDocFunctionText

    APIFilePath = APIDoc.FullName
    'No longer need the Header Files document open:
    APIDoc.Close wdDoNotSaveChanges

    'For expediency, am hard-coding name - should add dialog to browse to doc
    Set HeaderFilesDoc = Documents.Open("C:\Test\HeaderFilesDoc.doc")

    With HeaderFilesDoc.Content.Find
    .ClearFormatting
    .Text = strFunctionSig
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindStop
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    fMatch = .Execute
    End With

    'Deal with no match:
    If Not fMatch Then
    MsgBox "No match found in Header Files document!"
    TmpDoc1.Close wdDoNotSaveChanges
    Set TmpDoc1 = Nothing
    Documents.Open APIFilePath
    Application.ScreenUpdating = True
    Exit Sub
    Else
    Selection.Extend ")"
    HeaderFilesDocFunctionText = Selection.Text

    Set TmpDoc2 = Documents.Add
    TmpDoc2.Content = HeaderFilesDocFunctionText
    TmpDoc2.SaveAs "C:\Scratch\TmpDoc2.doc"
    strTmpDoc2Name = TmpDoc2.FullName

    'No longer need the API File document open:
    HeaderFilesDoc.Close wdDoNotSaveChanges

    TmpDoc1.Compare Name:=strTmpDoc2Name, CompareTarget:=wdCompareTargetNew

    TmpDoc1.Close wdDoNotSaveChanges
    TmpDoc2.Close wdDoNotSaveChanges

    Set TmpDoc1 = Nothing
    Set TmpDoc2 = Nothing
    Set APIDoc = Nothing
    Set HeaderFilesDoc = Nothing

    'Reopen original API doc:
    Documents.Open APIFilePath
    Application.ScreenUpdating = True
    End If
    End Sub[/codebox]
    Gary

Posting Permissions

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