Tickmark using epplus - c#

My problem is, when I am trying to generate my Excel file
I have some cells contains the tickmark symbol.
using (ExcelRange Rng = wsSheet.Cells[col])
{
Rng.Value = Beneficiary.IDentityOrFamilyBookCheck;// this value is ü
Rng.Style.Font.SetFromFont("Wingdings", 16);
Rng.Style.Font.Charset = 178;
}
in fact with the specified font and value it must appear as a check
but it is not
This is how it actually appears
This is how it must appear

Your Charset is wrong. Try Rng.Style.Font.Charset = 2; It is always good to do some reverse engineering. In this case create an Excel file with the Font and symbol you want and read the Style within your program.

I was able to discover the solution in my own way. Please note that Behnam's way is excellent also and can clarify the issue, but I did it in a different way.
I created an excel file containing the required symbol.
I changed the .xsls extension to .zip.
Iow I became able to show my excel file XML content and discover the actual Rng.Style.Font.Charset.

Related

How to get wrapped text from Excel cell?

I want to know how to get wrapped text from Excel cell using ClosedXML.
(ClosedXML version is 0.95.4, and use C#[Visualstudio 2017])
For example:
excel cell data (text) is following
abc
xyz
I want
abc
xyz
(=wrapped text), but I get abcxyz (=no wrapped text).
I tried several methods (as follows) and the results were the same.
tgtcell.RichText
tgtcell.GetString()
tgtcell.Value.ToString()
etc.
Can anyone tell me how to get it?
Now the cause is known. In the cell where the wrapped text was entered, the unwrapped one was mixed in. (Wrapped only by specifying the style format.)
Unfortunately, it was the cell that I tested, so it looked unreadable.
(this is more of an extended comment than a definitive answer)
I created an Excel file in which I typed ABC<Alt>+<Enter>xyz in cell A1. That puts ABC on one line and xyz under it (all in the same cell). Then I saved it and closed Excel.
Then I opened the file in the Microsoft "OpenXML Productivity Tool" (which unfortunately has been taken down from "Microsoft.com" but is still available on GitHub).
If I look in the Shared Strings section of the file, I can see this as XML:
<x:sst count="1" uniqueCount="1" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:si>
<x:t>ABCxyz</x:t>
</x:si>
</x:sst>
But, if I look at the reflected code (reflected into C#), I see:
public class GeneratedClass
{
// Creates an SharedStringTable instance and adds its children.
public SharedStringTable GenerateSharedStringTable()
{
SharedStringTable sharedStringTable1 = new SharedStringTable(){ Count = (UInt32Value)1U, UniqueCount = (UInt32Value)1U };
SharedStringItem sharedStringItem1 = new SharedStringItem();
Text text1 = new Text();
text1.Text = "ABC\nxyz";
sharedStringItem1.Append(text1);
sharedStringTable1.Append(sharedStringItem1);
return sharedStringTable1;
}
}
So it looks like Excel stores a Unix newline character between lines in a single cell. I don't know why that doesn't show up in the XML.
I'm far from an OpenXML expert, but I have used it several times successfully (mostly to generate files, not to parse them). I've never used ClosedXML. I don't have a clue what Wrapped Text means (nor does your explanation help). But, I can see the two lines of text in the file.
I don't know if this will help you - I hope so.

How can I export a piece of a DOCX file and keep the same paragraph numbering?

TL;DR:
How can I capture the paragraph numbering as a 'part' of the text and export it to a DOCX?
Problem
I have a document that's split into sections and sub-sections that reads similarly to a set of state statutes (Statute 208, with subsections Statute 208.1, Statute 208.2, etc.). We created this by modifying the numbering.xml file within the .docx zip.
I want to export a 'sub-section' (208.5) and its text to a separate .docx file. My VSTO add-in exports the text well enough, but the numbering resets to 208.1. This does make some sense as it's now the first paragraph with that <ilvl> in the document.
PDF works okay
Funnily enough, I'm able to call Word.Range's ExportAsFixedFormat function and export this selection to PDF just fine - even retaining the numbering. This led me down a path of trying to 'render' the selection, possibly as it would be printed, in order to throw it into a new .docx file, but I haven't figured that out, either.
What I've tried:
Range.ExportFragment() using both wdFormatStrictOpenXMLDocument and wdFormatDocumentDefaultas the wdSaveType values.
These export but also reset the numbering.
Document.PrintOut() using PrintToFile = true and a valid filename. I realize now that this, quite literally, generates 'printout instructions' and won't inject a new file at path filename with any valid file structure.
Plainly doesn't work. :)
Application.Selection.XML to a variable content and calling Document.Content.InsertXML(content) on a newly added Document object.
Still resets the numbering.
Code Section for Context
using Word = Microsoft.Office.Interop.Word;
Word.Range range = Application.ActiveDocument.Range(startPosition, endPosition);
range.Select();
//export to DOCX?
Application.Selection.Range.ExportFragment(
filename, Word.WdSaveFormat.wdFormatDocumentDefault);
You could use ConvertNumbersToText(wdNumberAllNumbers) before exporting, then _Document.Undo() or close without saving after the export.
There is some good information at this (dated) link that still should work with current Word APIs:
https://forums.windowssecrets.com/showthread.php/27711-Determining-which-ListTemplates-item-is-in-use-(VBA-Word-2000)
Information at that link suggests that you can create a name/handle for your ListTemplate so that you can reference it in code--as long as your statute-style bullets are associated with a named style for the document. The idea is to first name the ListTemplate that's associated with the statute bullet style for the active document and then reference that name when accessing the ListLevels collection.
For instance, you could have code that looks something like this:
ActiveDocument.Styles("StatutesBulletStyle").ListTemplate.Name = "StatuteBulletListTemplate";
After the above assignment, you can refer to the template by name:
ActiveDocument.ListTemplates("StatuteBulletListTemplate").ListLevels(1).StartAt = 5;
Using the above technique no longer requires that you try to figure out what the active template is...
Does that help?

Creating Word file from ObservableCollection with C#

I have an observable collection with a class that has 2 string properties: Word and Translation. I want to create a word file in format:
word = translation word = translation
word = translation word = translation...
The word document needs to be in 2 Columns (PageLayout) and the Word should be in bold.
I have first tried Microsoft.Office.Interop.Word.
PageSetup.TextColumns.SetCount(2) sets the PageLayout. As for the text itself I used a foreach loop and in each iteration I did this:
paragraph.Range.Text = Word + " = " + Translation;
object boldStart = paragraph.Range.Start;
object boldEnd = paragraph.Range.Start + Word.Length;
Word.Range boldPart = document.Range(boldStart, boldEnd);
boldPart.Bold = 1;
paragraph.Range.InsertParagraphAfter();
This does exactly what I want, but if there are 1000 items in the collection it takes about 10sec, much much more if the number is 10k+. I then used a StringBuilder and just set document.Content.Text = sb.ToString(); and that takes less than a sec, but I can't set the word to be bold that way.
Then I switched to using Open XML SDK 2.5, but even after reading the msdn documentation I still have no idea how to make just a part of the text bold, and I don't know if it's even possible to set PageLayout Columns count. The only thing I could do was to make it look the same as with Interop.Word, but with just 1 column and <1sec creation time.
Should I be using Interop.Word or Open XML (or maybe combined) for this? And can someone pls show me how to write this properly, so it doesn't take forever if the collection is relatively large? Any help is appreciated. :)
OOXML can be intimidating at first. http://officeopenxml.com/anatomyofOOXML.php has some good examples. Whenever you get confused unzip the docx and browse the contents to see how it's done.
The basic idea is you'd open Word, create a template with the styling you want and a code word to find the paragraph, then multiply the paragraph, replacing the text in that template with each word.
Your Word template would look like this:
Here's some pseudo code to get you started, assuming you have the SDK installed
var templateRegex = new Regex("\\[templateForWords\\]");
var wordPlacementRegex = new Regex("\\[word\\]");
var translationPlacementRegex = new Regex("\\[translation]\\]");
using (var document = WordprocessingDocument.Open(stream, true))
{
MainDocumentPart mainPart = document.MainDocumentPart;
// do your work here...
var paragraphTemplate = mainPart.Document.Body
.Descendants<Paragraph>()
.Where(p=>templateRegex.IsMatch(p.InnerText)); //pseudo
//... or whatever gives you the text of the Para, I don't have the SDK right now
foreach (string word in YourDictionary){
var paraClone = paragraphTemplate.Clone(); // pseudo
// you may need to do something like
// paraClone.Descendents<Text>().Where(t=>regex.IsMatch(t.Value))
// to find the exact element containing template text
paraClone.Text = templateRegex.Replace(paraClone.Text,"");// pseudo
paraClone.Text = wordPlacementRegex.Replace(paraClone.Text,word);
paraClone.Text = translationPlacementRegex.Replace(paraClone.Text,YourDictionary[word]);
paragraphTemplate.Parent.InsertAfter(paraClone,ParagraphTemplate); // pseudo
}
paragraphTemplate.Remove();
// document should auto-save
document.Package.Flush();
}
OpenXML is absolutely better, because it is faster, has less bugs, more reliable and flexible in runtime (especially in server environment). And it's not really difficult to find out how to make one or another element using OpenXML. As docx file is just a zip file with xml files inside, I open it and read the xml to get the idea, how word itself makes it. First of all, I create a document, then format it (in your case, you can create some file with two columns and bold words inside), save it, rename it to .zip file. Then open it, open "word" directory inside and the file "document.xml" inside the directory. This document contains essential part of xml, looking at this it's not difficult to figure out how to recreate it in OpenXML
Open XML is a much better option than Office COM. But the problem is that it is a low-level file format library that unlike Office COM doesn’t work on a high abstraction level. You might want to go that route but I recommend you to first consider looking into a commercial library that will give you the benefits of a high-level DOM without the need to have MS Word installed on the production machine. Our company recently purchased this toolkit which allows you to use template based approach and also DOM/programmatic approach to generate/modify/create documents.

.Net Aspose.Words reading from word document

I use Aspose to write to a word file and read and write to an excel file. I am trying to get Aspose.Words to read from a Word document but I keep getting error messages. I have followed examples from Aspose.com and those aren't useful. I posted on the forum and I still haven't heard back from them.
I am wanting to read these field codes (example: {fillin "Date" \d ""}) from each word document, which there are multiples of them. Once I am able to get those extracted, I want to put those in a List<string> and verify that they aren't duplicates. After I have gone through all the documents, I need to print that list into an excel spreadsheet.
Can someone help me resolve this error issues or tell me an easier way to go about this?
Issue #1 - won't recognize the file.
//string path = #"C:\Users\kbangert\Desktop\Karpel\HonoluluHIChargeCode2\Charge Language\10C104X.doc";
//string file = ConfigurationManager.AppSettings["filePath"] + "10C104X.doc";
//Document doc = new Document(path);
//Document doc = new Document(file);
Document doc = new Document(#"10C104.docx");
I have tried different techniques and I get the same errors - "UnsupportedFileFormatException was unhandled" or "FileCorreptionException was unhandled". I know the files are fine so is it the field codes that are causing this issue?
Issue #2 - Cannot resolve symbol 'Fields' or 'FieldCollection'
StringBuilder sb = new StringBuilder();
FieldCollection fields = doc.Range.Fields;
foreach (Field field in fields)
sb.AppendLine(field.GetFieldCode());
This came from the developers at Aspose and this throws the above errors.
For issue #1, there is no telling exactly why the file is failing, so you would need to get Aspose involved in that. However, we use the the following Aspose method to determine whether or not Aspose will be able to open the file:
Aspose.Words.FileFormatUtil.DetectFileFormat(fileName).LoadFormat
You should also double check to see if the file exists where your app expects it to exist before trying to open it using System.IO.File.Exists.
For issue #2 you need to add the namespace for the fields to the top of your class:
using Aspose.Words.Fields;
In addition, it looks like the developers may have provided information different than the version you are working with. In our code, the reference is to doc.Range.FormFields and the collection type is FormFieldCollection. I am not sure what the GetFieldCode equivalent is.

Selecting text by font in Word

Is there a way of extracting all lines that are using a particular font (size, is it bolded, font name, etc) in word via C#?
In addition, is there a way to find out what is the font for some text that is in the document?
My hunch is that there are functions in the Microsoft.Office.Interop.Word namespace that can do this, but I cannot seem to find them.
Edit: I am using word 2010.
You can loop through the document using the Find object from Word Interop. You can set the Find.Font.Name property for a Selection or Range from your document. Note that the Font interface has several Name* properties for various encodings.
EDIT
Here's the equivalent VBA code:
Dim selectionRange As Range
Set selectionRange = Application.ActiveDocument.Range
With selectionRange.Find
.ClearFormatting
.Format = True
.Font.NameBi = "Narkisim" //for doc without bidirectional script, use Name
Do While .Execute
MsgBox selectionRange.Text
Loop
End With
The object model from Word Interop is the same, see the link above.
Don't go asking me for C# code now... this is SO, we don't do silver platters. And if you're ever going to do serious work with the Office Interop API, you will need to be able to read VBA code.

Categories