Add line break to richt text content control - c#

I have a function which add text to a rich content control in word. I have succeeded to get the content control by searching voor the tag. Then I add text with line breaks to the content control, but it does not accept the line breaks. It simply add the text on one line.
I would run the function (as in code below) several times, and add each new text on a new line in de content control.
I've tried several options as giving here on stackoverflow, but it still does not work. Can you please help me?
//Insert Text to manual.
public static WordprocessingDocument InsertText(this WordprocessingDocument doc, string contentControlTag, string text)
{
SdtElement element = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>().FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>()?.Val == contentControlTag);
if (element == null)
throw new ArgumentException($"ContentControlTag \"{contentControlTag}\" doesn't exist.");
element.Descendants<Text>().First().Text = text;
return doc;
}

Unless your string starts with a line-break or paragraph-break, whatever you add to the content control will simply be appended to the same line as whatever line already contains the last character. And, although you've described it as a 'rich content control', you might reconfirm that is the case - depending on how they're configured, plain text content controls can also accept paragraph breaks.

Related

Adding text (Or getting CaretPosition) of RichTextBox in .Net Core

I have a basic text editor app, and I aim to add a feature where the user can click a button and add premade text after where their cursor is.
I currently have this (using some code I found online)
richTextBox1.CaretPosition.InsertTextInRun(s);
I intend for the string s to be the string to be added.
However, the RichTextBox in System.Windows.Forms does NOT contain a CaretPosition. I found one post from 2010 suggesting you use System.Windows.Control, however, that is no longer accessible in .Net Core, it depends on presentation framework.
So, is there any way I could get my goal (inserting a string after the mouse cursor, in a rich text box), in .net core?
Updated2:
Use the following code to fully satisfy the richtextbox of the text text environment.:
richTextBox1.Select(richTextBox1.SelectionStart, richTextBox1.TextLength);//Select everything after the cursor
string tmp = richTextBox1.SelectedText;//Copy them
richTextBox1.SelectedText = "";//Set to null
richTextBox1.AppendText("Hello world"+tmp);//Add the target string and add the original text
Updated1:
// Determine if there is any text in the Clipboard to paste into the text box.
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text) == true)
{
IDataObject dataObject = Clipboard.GetDataObject();
Clipboard.SetDataObject("Hello World");
richTextBox1.Paste();
Clipboard.SetDataObject(dataObject);
}
else
{
Clipboard.SetDataObject("Hello World");
richTextBox1.Paste();
}
This action preserves the contents of the original pasteboard.
Only works if the clipboard is data. I will continue to update after I think about it.
Original:
You only need to use the clipboard and paste method to insert the specified string after the specified cursor.
Clipboard.SetDataObject("Hello World");
richTextBox1.Paste();
Clipboard.Clear();
Change it yourself according to your needs.

Selenium C#: How to check/assert copied text? (Net6)

On my website, I can click on a button, which does copy text. In the screenshot below this is how it looks like:
After clicking on the copy text, it should copy the text Bitte einschalten und ausschalten äüöß 876543212345678 which can be seen on the bottom of the picture.
Now I would like to check, if the copy function worked and if the text on the webpage, is the same as the one which has been copied.
I was already searching for answers, but nothing worked for me.
My idea was to paste the text into the browser's URL field and then compare it, but it seems that selenium is not able to access this URL field.
There is also no other text field where I could paste the text inside.
Would appreciate any help!
EDIT: There was a method in C# which doesnt work in .NET Core anymore.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.clipboard?view=windowsdesktop-6.0
Looking for a other solution like this.
With a bit of JavaScript, you might be able to do this:
Create a text field using JavaScript.
Get the value of the text field.
var js = (IJavaScriptExecutor)driver;
var textareaId = DateTime.Now.Ticks.ToString();
var script = $#"
var textarea = document.createElement('textarea');
textarea.id = '{textareaId}';
document.body.appendChild(textarea);";
js.ExecuteScript(script);
var textarea = driver.FindElement(By.Id(textareaId));
// Paste clipboard into textarea
textarea.SendKeys(Keys.CONTROL + "v");
var clipboardText = textarea.GetProperty("value");
Just be aware of where this text area gets appends to the page. If it is hidden or partially obstructed by another element, you will get an ElementNotInteractableException. If this happens, pick a different element on the page when appending the textarea. Just replace document.body.appendChild(textarea) with a reference to a different element.
For example: document.getElementById('someOtherElementId').appendChild(textarea)

Replace the entire paragraph InnerText parameter with a new string. using OpenXML C#

I writing a utility that reads in a .docx template file using OpenXML in C#. The utility lists all paragraph by its heading and depending on the paragraph heading (configurable via a ini file) I have the option of editing the paragraph or removing the paragraph completely. I have everything working with the removing of the paragraph but I'm struggle to be able to replace all the paragraph text with a new one. I know about the below code but this doesn't do what I want because paragraph comes in many elements and I'm struggling to work out how I can replace the paragraph text. The paragraph text does come in its entirety in paragraph.InnerText but this cannot be edited. Is there a workaround? Thanks in advance.
foreach (Paragraph paragraph in paragraphs)
{
foreach (Run run in paragraph.Elements<Run>())
{
foreach (Text text in run.Elements<Text>())
{
Console.WriteLine (text.Text);
}
}
}
With a little help from another post I've solved my issue. It was quite simple in the end I just had to added the folllowing.
paragraph.RemoveAllChildren<Run>();
paragraph.AppendChild<Run>(new Run(new Text("New Paragraph Text")));

Reading a document from bottom

I have created a add-in for MS word. I have two buttons. Click on first move me forward by highlighting a range of words. On every second button click I want to go to the previous highlighted word. Can anybody help me in second button functionality. On button click one I have this code working fine.Now how to go the previously highlighted word range on every button2 click??
private void adxRibbonButton1_OnClick(object sender, IRibbonControl control, bool pressed)
{
object missing = System.Type.Missing;
Word.Document document = WordApp.ActiveDocument;
foreach(Word.Range docRange in document.Words)
{
if(docRange.HighlightColorIndex.Equals(Microsoft.Office.Interop.Word.WdColorIndex.wdRed))
{
docRange.HighlightColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdBlue;
docRange.Font.ColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdWhite;
break;
}
}
}
There's more than one way to approach this:
Use Word's built-in Find to search backwards in the document for the first instance of the changed highlighting.
Set two bookmarks, one for the current position of the code in the question and one for the previous position. The code sample below is for this variation.
string CurrentBkm = "_bkmCurrent";
string LastBkm= "_bkmLast";
if(docRange.HighlightColorIndex.Equals(Microsoft.Office.Interop.Word.WdColorIndex.wdRed))
{
docRange.HighlightColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdBlue;
docRange.Font.ColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdWhite;
if (document.Bookmarks.Exists(CurrentBkm))
{
document.Bookmarks.Add(LastBkm, document.Bookmarks[CurrentBkm].Range.Duplicate);
}
document.Bookmarks.Add(CurrentBkm, docRange);
break;
The code for button2 simply goes to the bookmark "_bkmLast":
string LastBkm= "_bkmLast";
document.Bookmarks[LastBkm].Range.Select();
Note that the bookmark name starts with an underscore _. This hides the bookmark in the Word UI so that it won't irritate the user in case the application settings show bookmark non-printing characters.
Note, also, that the code in the question could also work with Word's built-in Find functionality to search the formatting. This would almost certainly be more efficient than "walking" each word in the document and testing its highlight formatting. If you were to change your code to use Find the solution I provide with the bookmarks would still work.

Replacing Content Controls in OpenXML

I need something as a placeholder. I at first looked to Content Control as a solution but I'm having some problems with it.
I then looked into adding CustomXML to the .docx but turned away from that because of the i4i lawsuit.
Then I decided I would just plain change the text of the Content Control through OpenXML SDK 2.0 but even if it's so marked the Content Control doesn't go away. I guess that it doesn't know that the text changed unless it happens inside word.
I could perhaps just remove the CC and place text instead but I'm afraid of problems with format and styles it could bring and also it would kind of defy the purpose of the Content Control.
Then I started wondering if I could define my own placeholders that Word could recognize. Through Building blocks perhaps. It doesn't have to do anything except be easy to find using OpenXML and somehow taggable so I know what to replace it with. I'm not really sure what can be done with Building Blocks but I'm hoping it's do-able.
Not sure what solution would be best for me but what I need is:
a)Something that's easy to place in the template, perhaps predefined Content Control placeholders that you can place where you wan't and style as you like.
b)When the data has been added it removes all placeholders, it won't be modified again. It keeps the style/format defined in the placeholder.
TO RECAP, I need answer to either
How can I edit Content Controls in OpenXML SDK so they will be removed after text is added.
-OR-
Can I define my own custom OpenXML tag for a Word Document that I could then replace?
Perhaps this can help you,
private void DeleteSdtBlockAndKeepContent(MainDocumentPart mainDocumentPart, string sdtBlockTag)
{
List<SdtBlock> sdtList = mainDocumentPart.Document.Descendants<SdtBlock>().ToList();
SdtBlock sdtA = null;
foreach (SdtBlock sdt in sdtList)
{
if (sdt.SdtProperties.GetFirstChild<Tag>().Val.Value == sdtBlockTag)
{
sdtA = sdt;
break;
}
}
OpenXmlElement sdtc = sdtA.GetFirstChild<SdtContentBlock>();
OpenXmlElement parent = sdtA.Parent;
OpenXmlElementList elements = sdtc.ChildElements;
var mySdtc = new SdtContentBlock(sdtc.OuterXml);
foreach (OpenXmlElement elem in elements)
{
string text = parent.FirstChild.InnerText;
parent.Append((OpenXmlElement)elem.Clone());
}
sdtA.Remove();
}
Take a look at using a Field. The mail merge fields are designed for exactly this purpose.
I don't understand from your question if you are only interested in a solution that automatically removes the ContentControl/SDT when you modify it using the OpenXML SDK, or whether you want it to disappear after the content is modifed programmatically or by a user.
If the former, I think you'll have to remove it yourself as Bilel suggested. If the latter, you should look at this property: ContentControl.Temporary ("the ContentControl is automatically deleted when the user types in the control, or when the text in the control is changed programmatically. When the ContentControl is automatically deleted from the document, the text in the control remains in the document.")

Categories