none
String Parameter too long - writing to a Word doc using C#

    Question

  •  

    Hi Guys

      My app uses the Word Object Model and creates Word documents. However I am facing one particular issue when I try to implement a search and replace functionality. When the string to be replaced is more than 255 chars I get an error message saying string parameter is too long. Below is the c# code (in brief)..

     

    app.Application.Selection.Find.Text = (string)findMe;

    app.Application.Selection.Find.Replacement.ClearFormatting();

     

    app.Application.Selection.Find.Replacement.Text = (string)replaceMe;

    app.Application.Selection.Find.Execute(

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref replaceAll, ref missing, ref missing, ref missing, ref missing);

     

    If replaceMe is less than 255 chars then this code runs fine. However when it exceeds 255 char the ..Find.Replacement.Text is unable to hold more than 255 chars..

     

    Searching the net has given some decent solutions but most of them are related to Visual Basic (VBA) programming, hence I wasn't able to co relate it well with c#.

    If anyone can throw some light on how to tackle this in a C# environment, then that would be really useful .

     

    Thanks!

    Muzammil Misbah

    Wednesday, July 30, 2008 5:14 PM

Answers

  • Hi Tim/Cindy!

     

    I was able to resolve this issue. I didn't know it would be this simple! Anyways please test it out and see whether it works.

     

    Been using Word 2003 (Object 11)

     

    Here is the code (search and replace method)

     

    public static void ReplaceTextInWordDoc(Object findMe, Object replaceMe, ApplicationClass app)

    {

    try

    {

    object replaceAll = Word.WdReplace.wdReplaceAll;

    object missing = System.Reflection.Missing.Value;

    app.Application.Selection.Find.ClearFormatting();

    app.Application.Selection.Find.Text = (string)findMe;

    app.Application.Selection.Find.Replacement.ClearFormatting();

     

    if (replaceMe.ToString().Length < 250) // Normal execution

    {

    app.Application.Selection.Find.Replacement.Text = (string)replaceMe;

    app.Application.Selection.Find.Execute(

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref replaceAll, ref missing, ref missing, ref missing, ref missing);

    }

    else  // Some real simple logic!!

    {

    app.Application.Selection.Find.Execute(

    ref findMe, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing);

     

    // the area where the findMe is located in the Document is selected.

    // Hence when you execute the statement below the replaceMe string is

    // placed in the area selected, which is what we wanted!

     

    app.Application.Selection.Text = (string)replaceMe;

    }

    }

    catch (Exception ex)

    {

    BaseClasses.Utils.MiscUtils.RegisterJScriptAlert(null, "UNIQUE_SCRIPTKEY", ex.Message);

    }

    }

     

     

    Hope this helps

     

    Muzammil Misbah

     

    Thursday, July 31, 2008 3:56 PM
  • OK, I found a good solution. Forget the *** I wrote yesterday. If it helps, here's my code:

    Code Snippet

    // Finds text in a document, returns a Range containing that text (or NULL when not found)
    public Word.Range findText(String toFind)
    {
    // Range = Whole document
    Word.Range searchArea = Application.ActiveDocument.Range(ref missing, ref missing);
    searchArea.Find.ClearFormatting();

    // Save the current selection
    Word.Range start = Application.Selection.Range;

    // If toFind > 255, cut it at 255
    object findText = null;
    bool longString = false;
    if (toFind.Length < 254)
    findText = toFind;
    else
    {
    findText = toFind.Substring(0, 254);
    longString = true;
    }

    // Look for toFind
    if (searchArea.Find.Execute(ref findText,
    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing))
    {
    // The first 255 chars match, continue search
    if (longString)
    {
    // If the original toFind > 255
    bool keepSearching = true;
    object unit = Word.WdUnits.wdCharacter;
    object count = 1;

    // Continue extending the searcharea char by char
    while (keepSearching)
    {
    // ... until it equals toFind
    if (searchArea.Text == toFind)
    keepSearching = false;
    else
    {
    // Or it's not found (current text is longer than toFind)
    if (searchArea.Text.Length > toFind.Length)
    keepSearching = false;
    else
    searchArea.MoveEnd(ref unit, ref count);
    }
    }

    // After the loop, if toFind is found, select it
    if (searchArea.Text == toFind)
    searchArea.Select();

    }
    }
    else // The first 255 chars do not match
    searchArea = null;

    // Restore the initial selection
    start.Select();

    // Return the found result
    return searchArea;
    }


           

    Thanks anyway Smile
    Friday, August 01, 2008 3:45 PM

All replies

  • I'm guessing that the solutions you've found don't use Replace (or Replace ALL)? Instead, if the Find is successful the text is inserted directly into the Found range, then the loop continues until Find is no longer successful?

     

    Take a look at the third post in this forum discussion. This is the basic structure you need. Where the sample code tests find.found and stores the range in an array is where you'd assign the text to the range.

    Wednesday, July 30, 2008 5:35 PM
    Moderator
  • Same problem here. I can't use your solution because the it's not the replacement String that is too long (it could be, though), but the toFind String is too long ! I tried to cut the toFind String into 254 lenght strings and then make a recursive call of my searchAndReplace function, replacing all the 254-long parts by "" and only replacing the last one by my replacement String, but I got an unexptected stackoverflow exception.

    How could my function find and replace Strings that are longer than 255 (both toFind and replacement, in the worst case) ?

    Regards,
    Tim
    Wednesday, July 30, 2008 8:12 PM
  • Hi Tim

     TheParadoX wrote:
    Same problem here. I can't use your solution because the it's not the replacement String that is too long (it could be, though), but the toFind String is too long ! I tried to cut the toFind String into 254 lenght strings and then make a recursive call of my searchAndReplace function, replacing all the 254-long parts by "" and only replacing the last one by my replacement String, but I got an unexptected stackoverflow exception.

    How could my function find and replace Strings that are longer than 255 (both toFind and replacement, in the worst case) ?

    Can you provide a bit more information about this scenario?

     

    1. Version of Word

     

    2. Why your search string needs to be so long (understanding that will help my intuition pick out alternative approaches)

     

    FWIW recursive calls always run the danger of a stack overflow. Can't you structure this so it isn't recursive? Just loop normally until a condition is met (or is no longer met)?

    Thursday, July 31, 2008 8:36 AM
    Moderator
  • Hi

    Thank you for the replies.

    I am still looking into this as I need to get some good grips with the Object model first.

    One good reference I obtained was this: http://gregmaxey.mvps.org/Find_Long_String.htm

     

    However since it was in VB I wasn't able to co relate it well with C#. If anyone can help me in that in that would be great!

     

    Thanks!

     

     

    Thursday, July 31, 2008 11:56 AM

  • Hi,

    1 - My Word version is 2003 (11.5604.6408).
    2 - I need the user to be able to replace some sentences. When this sentence is longer than 255 chars (which is not too long after all), the replacement sentence will most probably be that long too. So both find and replace methods will not work.

    My old searchAndReplace works like this (and it does not support 255+ chars strings)

    public void SearchReplace(String toFind, String replacement)
    {
                    Word.Range start = Application.Selection.Range;
                    Word.Range searchArea = Application.ActiveDocument.Range(ref missing, ref missing);
                   
              
                    searchArea.Find.ClearFormatting();
                    searchArea.Find.Text = toFind;
                    searchArea.Find.Replacement.ClearFormatting();
                    searchArea.Find.Replacement.Text = Tools.converLineBreaks(replacement);

                    object replaceAll = Word.WdReplace.wdReplaceOne;

                    searchArea.Find.Execute(
                        ref missing, ref missing, ref missing, ref missing, ref missing,
                        ref missing, ref missing, ref missing, ref missing, ref missing,
                        ref replaceAll, ref missing, ref missing, ref missing, ref missing);

                    start.Select();           
    }

    So I tried to modify it like this:

    public void SearchReplace(String toFind, String replacement)
    {

                    Word.Range start = Application.Selection.Range;
                    Word.Range searchArea = Application.ActiveDocument.Range(ref missing, ref missing);
                   
                if (toFind.Length < 254)
                {
    // Same replacement code as before
                }
                else // String longer than 255 chars
                {

    // Splitting the toFind String into smaller strings and putting it in a list
                    String copyToFind = toFind;
                    List<String> tempList = new List<String>();
                    bool endNotReached = true;
                    while(endNotReached)
                    {
                        if (copyToFind.Length > 254)
                        {
                            tempList.Add(copyToFind.Substring(0, 254));
                            copyToFind = copyToFind.Substring(254);
                        }
                        else
                        {
                            tempList.Add(copyToFind);
                            endNotReached = false;
                        }                   
                    }

    // Delete all smaller strings and only replace the last bit by the replacement string
                    for(int i = 0; i < tempList.Count; i++)
                    {
                        if (i == tempList.Count - 1)
                            SearchReplace(tempListIdea.ToString(), replacement);
                        else
                            deleteText(tempListIdea.ToString());
                    }

                }           
    }

    I don't like this solution anyway, I'll try to find a better way to implement this, it looks awful for now. Any help is welcome Smile

    Regards,
    Tim
    Thursday, July 31, 2008 2:36 PM
  • Hi Tim/Cindy!

     

    I was able to resolve this issue. I didn't know it would be this simple! Anyways please test it out and see whether it works.

     

    Been using Word 2003 (Object 11)

     

    Here is the code (search and replace method)

     

    public static void ReplaceTextInWordDoc(Object findMe, Object replaceMe, ApplicationClass app)

    {

    try

    {

    object replaceAll = Word.WdReplace.wdReplaceAll;

    object missing = System.Reflection.Missing.Value;

    app.Application.Selection.Find.ClearFormatting();

    app.Application.Selection.Find.Text = (string)findMe;

    app.Application.Selection.Find.Replacement.ClearFormatting();

     

    if (replaceMe.ToString().Length < 250) // Normal execution

    {

    app.Application.Selection.Find.Replacement.Text = (string)replaceMe;

    app.Application.Selection.Find.Execute(

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref replaceAll, ref missing, ref missing, ref missing, ref missing);

    }

    else  // Some real simple logic!!

    {

    app.Application.Selection.Find.Execute(

    ref findMe, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing,

    ref missing, ref missing, ref missing, ref missing, ref missing);

     

    // the area where the findMe is located in the Document is selected.

    // Hence when you execute the statement below the replaceMe string is

    // placed in the area selected, which is what we wanted!

     

    app.Application.Selection.Text = (string)replaceMe;

    }

    }

    catch (Exception ex)

    {

    BaseClasses.Utils.MiscUtils.RegisterJScriptAlert(null, "UNIQUE_SCRIPTKEY", ex.Message);

    }

    }

     

     

    Hope this helps

     

    Muzammil Misbah

     

    Thursday, July 31, 2008 3:56 PM

  • Well this doesn't solve the problem because you can only search for strings that are shorter than 255 chars.
    For my function, it's a infinite recursive call .. I'm working on it. There mus be a more elegant solution ...

    EDIT: I edited my first function (see above), it now works if the toFind string is > 255 chars. But I have to find a way to make it work when the replacement String is also > 255 chars Tongue Tied
    Thursday, July 31, 2008 4:31 PM
  • OK, I found a good solution. Forget the *** I wrote yesterday. If it helps, here's my code:

    Code Snippet

    // Finds text in a document, returns a Range containing that text (or NULL when not found)
    public Word.Range findText(String toFind)
    {
    // Range = Whole document
    Word.Range searchArea = Application.ActiveDocument.Range(ref missing, ref missing);
    searchArea.Find.ClearFormatting();

    // Save the current selection
    Word.Range start = Application.Selection.Range;

    // If toFind > 255, cut it at 255
    object findText = null;
    bool longString = false;
    if (toFind.Length < 254)
    findText = toFind;
    else
    {
    findText = toFind.Substring(0, 254);
    longString = true;
    }

    // Look for toFind
    if (searchArea.Find.Execute(ref findText,
    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing))
    {
    // The first 255 chars match, continue search
    if (longString)
    {
    // If the original toFind > 255
    bool keepSearching = true;
    object unit = Word.WdUnits.wdCharacter;
    object count = 1;

    // Continue extending the searcharea char by char
    while (keepSearching)
    {
    // ... until it equals toFind
    if (searchArea.Text == toFind)
    keepSearching = false;
    else
    {
    // Or it's not found (current text is longer than toFind)
    if (searchArea.Text.Length > toFind.Length)
    keepSearching = false;
    else
    searchArea.MoveEnd(ref unit, ref count);
    }
    }

    // After the loop, if toFind is found, select it
    if (searchArea.Text == toFind)
    searchArea.Select();

    }
    }
    else // The first 255 chars do not match
    searchArea = null;

    // Restore the initial selection
    start.Select();

    // Return the found result
    return searchArea;
    }


           

    Thanks anyway Smile
    Friday, August 01, 2008 3:45 PM
  • Hi Muzammil Misbah,

       Your solution for string parameter too long is great but i having some issues with the solution. first time if the string is more then 250 characters its working fine and for the second time its not replacing 

      I really appreciate if you could find the error..

    Thank's

    Ram

    Thursday, June 17, 2010 1:30 AM
  • Here is the Solution:

    object courseslistobj = "FindText";

    \\Find Text

    wordApp.Application.Selection.Find.Execute(courseslistobj, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1, missing__1);

    \\Replace Text :

    wordApp.Application.Selection.Text = (string)"My New Text" ;

    • Proposed as answer by CMoussalli Sunday, June 16, 2013 10:14 AM
    Sunday, June 16, 2013 10:13 AM