Print attribute in the block in a tabular form in autocad - c#

This is my code which return me attribute values in the selected block,
but I want these values in a table to show on the dwg file. And the text must be single mtext object.
[CommandMethod("NLTAB")]
public void ListAttributes()
{
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Editor ed = acDoc.Editor;
Database db = acDoc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
TypedValue[] filList = new TypedValue[2] { new TypedValue((int)DxfCode.Start, "INSERT"), new TypedValue((int)DxfCode.HasSubentities, 1) };
SelectionFilter filter = new SelectionFilter(filList);
PromptSelectionOptions opts = new PromptSelectionOptions();
opts.MessageForAdding = "Select block references: ";
PromptSelectionResult res = ed.GetSelection(opts, filter);
// Do nothing if selection is unsuccessful
if (res.Status != PromptStatus.OK)
return;
SelectionSet selSet = res.Value;
ObjectId[] idArray = selSet.GetObjectIds();
PromptPointResult ppr;
PromptPointOptions ppo = new PromptPointOptions("");
ppo.Message = "\n Select the place for print output:";
//get the coordinates from user
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
Point3d startPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
Vector3d disp = new Vector3d(0.0, -2.0 * db.Textsize, 0.0);
TextStyleTable ts = (TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead);
ObjectId mtStyleid = db.Textstyle;
if (ts.Has("NAL-TEXT"))
{
mtStyleid = ts["NAL-FORMAT"];
}
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
MText _outputHeading = new MText();
_outputHeading.Location = startPoint;
_outputHeading.Width = 75.207;
_outputHeading.Height = 1.488;
_outputHeading.TextStyleId = mtStyleid;
string file = acDoc.Name;
string str1 = Path.GetFileNameWithoutExtension(file);
//string str1 = ("534-W10A-R1");
//var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
Match match = Regex.Match(str1, #"^(\w+-[CSDWM]\d+[A-Z]-.)$");
var pattern = #"^(\d+)-[A-Z](\d+)([A-Z])-";
var groups = Regex.Match(str1, pattern).Groups;
var _projectCode = groups[1].Value;
var _phaseCode = _projectCode + "-" + groups[2].Value;
var _zoneCode = _phaseCode + groups[3].Value;
curSpace.AppendEntity(_outputHeading);
tr.AddNewlyCreatedDBObject(_outputHeading, true);
db.TransactionManager.QueueForGraphicsFlush();
startPoint += disp;
HashSet<string> attValues = new HashSet<string>();
foreach (ObjectId blkId in idArray)
{
BlockReference blkRef = (BlockReference)tr.GetObject(blkId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForWrite);
AttributeCollection attCol = blkRef.AttributeCollection;
foreach (ObjectId attId in attCol)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);
string str = (attRef.TextString);
string tag = attRef.Tag;
if (attValues.Contains(str))
continue;
if (btr.Name == "NAL-TAG crs ref")
{
var curSpace1 = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
MText mtext = new MText();
mtext.Location = startPoint;
mtext.Contents = tag.ToString() + " : " + str + "\n";
//ed.WriteMessage(text);
curSpace.AppendEntity(mtext);
tr.AddNewlyCreatedDBObject(mtext, true);
db.TransactionManager.QueueForGraphicsFlush();
attValues.Add(str);
startPoint += disp;
}
}
}
tr.Commit();
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage(("Exception: " + ex.Message));
}
}
}

To crate a table, at this blog post, you'll find a sample code in C# that should work for you. The result should look like the image below.
And here is the source code. After creating the table, if you really need the texts, you can call .Explode() on it and extract all the text entities.
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace TableCreation
{
public class Commands
{
[CommandMethod("CRT")]
static public void CreateTable()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptPointResult pr =
ed.GetPoint("\nEnter table insertion point: ");
if (pr.Status == PromptStatus.OK)
{
Table tb = new Table();
tb.TableStyle = db.Tablestyle;
tb.NumRows = 5;
tb.NumColumns = 3;
tb.SetRowHeight(3);
tb.SetColumnWidth(15);
tb.Position = pr.Value;
// Create a 2-dimensional array
// of our table contents
string[,] str = new string[5, 3];
str[0, 0] = "Part No.";
str[0, 1] = "Name ";
str[0, 2] = "Material ";
str[1, 0] = "1876-1";
str[1, 1] = "Flange";
str[1, 2] = "Perspex";
str[2, 0] = "0985-4";
str[2, 1] = "Bolt";
str[2, 2] = "Steel";
str[3, 0] = "3476-K";
str[3, 1] = "Tile";
str[3, 2] = "Ceramic";
str[4, 0] = "8734-3";
str[4, 1] = "Kean";
str[4, 2] = "Mostly water";
// Use a nested loop to add and format each cell
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
tb.SetTextHeight(i, j, 1);
tb.SetTextString(i, j, str[i, j]);
tb.SetAlignment(i, j, CellAlignment.MiddleCenter);
}
}
tb.GenerateLayout();
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
BlockTable bt =
(BlockTable)tr.GetObject(
doc.Database.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
btr.AppendEntity(tb);
tr.AddNewlyCreatedDBObject(tb, true);
tr.Commit();
}
}
}
}
}

Related

EPPlus To Copy Worksheet From Workbook1 to Workbook2

I have a template workbook with a sheet called ProdData, I need to copy this worksheet to my current workbook.
Using C# and EPPlus, how can I copy a worksheet from one workbook to another? When I look at intellisense it seems to only show that I can copy from within the same workbook.
How do I copy the worksheet to a NEW workbook?
This works for me.
public static void CopySheetValues(string sourcePath, string sheetName, string destPath)
{
using (var src = new ExcelPackage(new FileInfo(sourcePath)))
using (var dest = new ExcelPackage(new FileInfo(destPath)))
{
var wsSrc = src.Workbook.Worksheets[1];
var wsDest = dest.Workbook.Worksheets[wsSrc.Name] ?? dest.Workbook.Worksheets.Add(wsSrc.Name);
for (var r = 1; r <= wsSrc.Dimension.Rows; r++)
{
Console.WriteLine("Row: " + r.ToString());
for (var c = 1; c <= wsSrc.Dimension.Columns; c++)
{
Console.WriteLine("Column: " + c.ToString());
var cellSrc = wsSrc.Cells[r, c];
var cellDest = wsDest.Cells[r, c];
if (cellDest.ToString() == "E10")
{
}
Console.WriteLine(cellDest.ToString());
// Copy value
cellDest.Value = cellSrc.Value;
// Copy cell properties
cellDest.Style.Numberformat = cellSrc.Style.Numberformat;
cellDest.Style.Font.Bold = cellSrc.Style.Font.Bold;
if (cellSrc.Style.Fill.BackgroundColor.Rgb != null)
{
if (cellSrc.Style.Fill.BackgroundColor.Rgb != "")
{
var color = cellSrc.Style.Fill.BackgroundColor.Rgb;
cellDest.Style.Fill.PatternType = ExcelFillStyle.Solid;
cellDest.Style.Fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#" + color));//.SetColor(color);
}
else
{
cellDest.Style.Fill.PatternType = ExcelFillStyle.Solid;
cellDest.Style.Fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#808080"));//.SetColor(color);
}
}// TODO... Add any additional properties that you may want to copy over
cellDest.Style.HorizontalAlignment =
cellSrc.Style.HorizontalAlignment;
cellDest.Style.VerticalAlignment =
cellSrc.Style.VerticalAlignment;
cellDest.Style.Border.Right.Style =
cellSrc.Style.Border.Right.Style;
cellDest.Style.Border.Left.Style =
cellSrc.Style.Border.Left.Style;
cellDest.Style.Border.Top.Style = cellSrc.Style.Border.Top.Style;
cellDest.Style.Border.Bottom.Style =
cellSrc.Style.Border.Bottom.Style;
cellDest.Style.WrapText = cellSrc.Style.WrapText;
}
}
dest.Save();
}
}

Parsing semi colon delimeter file

I have a CSV file but the delimiter is a semi colon ; and each column is enclosed with double quotes. There are also occurrences of ; in some values such as & amp;
I am using TextFieldParser to parse the file. This is the sample data:
"A001";"RT:This is a tweet"; "http://www.whatever.com/test/module & amp;one"
For the above example , I am getting more columns/fields than what I should get.
Field[0] = "A001"
Field[1] = "RT:This is a tweet"
Field[2] = "http://www.whatever.com/test/module&amp"
Field[3] = "one"
This is my code. What changes need to be done to handle such scenario?
using (var parser = new TextFieldParser(fileName))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
parser.TrimWhiteSpace = true;
parser.HasFieldsEnclosedInQuotes = false;
int rowIndex = 0;
PropertyInfo[] properties = typeof(TwitterData).GetProperties();
while (parser.PeekChars(1) != null)
{
var cleanFieldRowCells = parser.ReadFields().Select(
f => f.Trim(new[] { ' ', '"' }));
var twitter = new TwitterData();
int index = 0;
foreach (string c in cleanFieldRowCells)
{
string str = c;
if (properties[index].PropertyType == typeof(DateTime))
{
string twitterDateTemplate = "ddd MMM dd HH:mm:ss +ffff yyyy";
DateTime createdAt = DateTime.ParseExact(str, twitterDateTemplate, new System.Globalization.CultureInfo("en-AU"));
properties[index].SetValue(twitter, createdAt);
}
else
{
properties[index].SetValue(twitter, str);
}
index++;
}
}
-Alan-
Using the two sample strings you have above and setting the HasFieldsEnclosedInQuotes property to true works for me.
string LINES = #"
""A001"";""RT:This is a tweet""; ""http://www.whatever.com/test/module&one""
""A001"";""RT: Test1 ; Test2"";""test.com"";
";
using (var sr = new StringReader(LINES))
{
using (var parser = new TextFieldParser(sr))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
parser.TrimWhiteSpace = true;
parser.HasFieldsEnclosedInQuotes = true;
while (parser.PeekChars(1) != null)
{
var cleanFieldRowCells = parser.ReadFields().Select(
f => f.Trim(new[] { ' ', '"' })).ToArray();
Console.WriteLine("New Line");
for (int i = 0; i < cleanFieldRowCells.Length; ++i)
{
Console.WriteLine(
"Field[{0}] = [{1}]", i, cleanFieldRowCells[i]
);
}
Console.WriteLine("{0}", new string('=', 40));
}
}
}
OUTPUT:
New Line
Field[0] = [A001]
Field[1] = [RT:This is a tweet]
Field[2] = [http://www.whatever.com/test/module&one]
========================================
New Line
Field[0] = [A001]
Field[1] = [RT: Test1 ; Test2]
Field[2] = [test.com]
Field[3] = []
========================================

How do you mail merge a word document in c#

What I'm trying to achieve
In my c# application I would like to generate a report (word document) from data in my application, I figured that the best way to do this would be to perform something like a mail merge using the data source from my application.
What I've tried
I tried following this
Mail Merge into word
however this uses GemBox which you need to pay for
I have tried using Microsoft.Office.Interop.Word however I fell
short when I didn't know how to reference the saved template document:
Dictionary<string, string> MailMerge = new Dictionary<string, string>()
{
{ "ID", "123" },
{ "Name", "Test" },
{ "Address1", "Test" },
{ "Address2", "Test" },
{ "Address3", "Test" },
{ "Address4", "Test" },
{ "PostCode", "Test" },
{ "Year End", "Test" },
{ "SicCode", "123" },
};
Document doc = new Document();
doc.MailMerge.Execute(MailMerge);
Summary
I'm looking for some guidance as to what to research further as I believe there must be a 'standard' way of doing this.
Can't believe third party software charge thousands for interface functions with Word. I have perfectly solved this mail merge thing in my project -- no third party, no particular demands on IIS, just use OpenXML.
So, add these 4 functions to your project:
public static void dotx2docx(string sourceFile, string targetFile)
{
MemoryStream documentStream;
using (Stream tplStream = File.OpenRead(sourceFile))
{
documentStream = new MemoryStream((int)tplStream.Length);
CopyStream(tplStream, documentStream);
documentStream.Position = 0L;
}
using (WordprocessingDocument template = WordprocessingDocument.Open(documentStream, true))
{
template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
MainDocumentPart mainPart = template.MainDocumentPart;
mainPart.DocumentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
new Uri(targetFile, UriKind.Absolute));
mainPart.Document.Save();
}
File.WriteAllBytes(targetFile, documentStream.ToArray());
}
public static void CopyStream(Stream source, Stream target)
{
if (source != null)
{
MemoryStream mstream = source as MemoryStream;
if (mstream != null) mstream.WriteTo(target);
else
{
byte[] buffer = new byte[2048];
int length = buffer.Length, size;
while ((size = source.Read(buffer, 0, length)) != 0)
target.Write(buffer, 0, size);
}
}
}
public static void Mailmerge(string templatePath, string DestinatePath, DataRow dr, DataColumnCollection columns)
{
try
{
dotx2docx(templatePath, DestinatePath);
}
catch //incase the server does not support MS Office Word 2003 / 2007 / 2010
{
File.Copy(templatePath, DestinatePath, true);
}
using (WordprocessingDocument doc = WordprocessingDocument.Open(DestinatePath, true))
{
var allParas = doc.MainDocumentPart.Document.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>();
Text PreItem = null;
string PreItemConstant = null;
bool FindSingleAnglebrackets = false;
bool breakFlag = false;
List<Text> breakedFiled = new List<Text>();
foreach (Text item in allParas)
{
foreach (DataColumn cl in columns)
{
//<Today>
if (item.Text.Contains("«" + cl.ColumnName + "»") || item.Text.Contains("<" + cl.ColumnName + ">"))
{
item.Text = item.Text.Replace("<" + cl.ColumnName + ">", dr[cl.ColumnName].ToString())
.Replace("«" + cl.ColumnName + "»", dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else if //<Today
(item.Text != null
&& (
(item.Text.Contains("<") && !item.Text.Contains(">"))
|| (item.Text.Contains("«") && !item.Text.Contains("»"))
)
&& (item.Text.Contains(cl.ColumnName))
)
{
FindSingleAnglebrackets = true;
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"\<" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"\«" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
else if //Today> or Today
(
PreItemConstant != null
&& (
(PreItemConstant.Contains("<") && !PreItemConstant.Contains(">"))
|| (PreItemConstant.Contains("«") && !PreItemConstant.Contains("»"))
)
&& (item.Text.Contains(cl.ColumnName))
)
{
if (item.Text.Contains(">") || item.Text.Contains("»"))
{
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else
{
FindSingleAnglebrackets = true;
}
if (PreItemConstant == "<" || PreItemConstant == "«")
{
PreItem.Text = "";
}
else
{
PreItem.Text = global::System.Text.RegularExpressions.Regex.Replace(PreItemConstant, #"\<" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
PreItem.Text = global::System.Text.RegularExpressions.Regex.Replace(PreItemConstant, #"\«" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
if (PreItemConstant.Contains("<") || PreItemConstant.Contains("«")) // pre item is like '[blank]«'
{
PreItem.Text = PreItem.Text.Replace("<", "");
PreItem.Text = PreItem.Text.Replace("«", "");
}
if (item.Text.Contains(cl.ColumnName + ">") || item.Text.Contains(cl.ColumnName + "»"))
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\»", dr[cl.ColumnName].ToString());
}
else
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"(?!\w)", dr[cl.ColumnName].ToString());
}
}
else if (FindSingleAnglebrackets && (item.Text.Contains("»") || item.Text.Contains(">")))
{
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"(?<!\w)" + cl.ColumnName + #"\»", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\>", "");
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\»", "");
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
}
else if (item.Text.Contains("<") || item.Text.Contains("«")) // no ColumnName
{
}
} //end of each columns
PreItem = item;
PreItemConstant = item.Text;
if (breakFlag
|| (item.Text.Contains("<") && !item.Text.Contains(">"))
|| (item.Text.Contains("«") && !item.Text.Contains("»"))
)
{
breakFlag = true;
breakedFiled.Add(item);
string combinedfiled = "";
foreach (Text t in breakedFiled)
{
combinedfiled += t.Text;
}
foreach (DataColumn cl in columns)
{
//<Today>
if (combinedfiled.Contains("«" + cl.ColumnName + "»") || combinedfiled.Contains("<" + cl.ColumnName + ">"))
{
//for the first part, remove the last '<' and tailing content
breakedFiled[0].Text = global::System.Text.RegularExpressions.Regex.Replace(breakedFiled[0].Text, #"<\w*$", "");
breakedFiled[0].Text = global::System.Text.RegularExpressions.Regex.Replace(breakedFiled[0].Text, #"<\w*$", "");
//remove middle parts
foreach (Text t in breakedFiled)
{
if (!t.Text.Contains("<") && !t.Text.Contains("«") && !t.Text.Contains(">") && !t.Text.Contains("»"))
{
t.Text = "";
}
}
//for the last part(as current item), remove leading content till the first '>'
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\>", dr[cl.ColumnName].ToString());
item.Text = global::System.Text.RegularExpressions.Regex.Replace(item.Text, #"^\s*\»", dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
breakFlag = false;
breakedFiled.Clear();
break;
}
}
}
}//end of each item
#region go through footer
MainDocumentPart mainPart = doc.MainDocumentPart;
foreach (FooterPart footerPart in mainPart.FooterParts)
{
Footer footer = footerPart.Footer;
var allFooterParas = footer.Descendants<Text>();
foreach (Text item in allFooterParas)
{
foreach (DataColumn cl in columns)
{
if (item.Text.Contains("«" + cl.ColumnName + "»") || item.Text.Contains("<" + cl.ColumnName + ">"))
{
item.Text = (string.IsNullOrEmpty(dr[cl.ColumnName].ToString()) ? " " : dr[cl.ColumnName].ToString());
FindSingleAnglebrackets = false;
}
else if (PreItem != null && (PreItem.Text == "<" || PreItem.Text == "«") && (item.Text.Trim() == cl.ColumnName))
{
FindSingleAnglebrackets = true;
PreItem.Text = "";
item.Text = (string.IsNullOrEmpty(dr[cl.ColumnName].ToString()) ? " " : dr[cl.ColumnName].ToString());
}
else if (FindSingleAnglebrackets && (item.Text == "»" || item.Text == ">"))
{
item.Text = "";
FindSingleAnglebrackets = false;
}
}
PreItem = item;
}
}
#endregion
#region replace \v to new Break()
var body = doc.MainDocumentPart.Document.Body;
var paras = body.Elements<Paragraph>();
foreach (var para in paras)
{
foreach (var run in para.Elements<Run>())
{
foreach (var text in run.Elements<Text>())
{
if (text.Text.Contains("MS_Doc_New_Line"))
{
string[] ss = text.Text.Split(new string[] { "MS_Doc_New_Line" }, StringSplitOptions.None);
text.Text = text.Text = "";
int n = 0;
foreach (string s in ss)
{
n++;
run.AppendChild(new Text(s));
if (n != ss.Length)
{
run.AppendChild(new Break());
}
}
}
}
}
}
#endregion
doc.MainDocumentPart.Document.Save();
}
}
public static void MergeDocuments(params string[] filepaths)
{
//filepaths = new[] { "D:\\one.docx", "D:\\two.docx", "D:\\three.docx", "D:\\four.docx", "D:\\five.docx" };
if (filepaths != null && filepaths.Length > 1)
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(#filepaths[0], true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
for (int i = 1; i < filepaths.Length; i++)
{
string altChunkId = "AltChunkId" + i;
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(
AlternativeFormatImportPartType.WordprocessingML, altChunkId);
using (FileStream fileStream = File.Open(#filepaths[i], FileMode.Open))
{
chunk.FeedData(fileStream);
}
DocumentFormat.OpenXml.Wordprocessing.AltChunk altChunk = new DocumentFormat.OpenXml.Wordprocessing.AltChunk();
altChunk.Id = altChunkId;
//new page, if you like it...
mainPart.Document.Body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
//next document
mainPart.Document.Body.InsertAfter(altChunk, mainPart.Document.Body.Elements<Paragraph>().Last());
}
mainPart.Document.Save();
myDoc.Close();
}
}
And use them like this:
DataTable dt = new DataTable();
dt.Columns.Add("Date");
dt.Columns.Add("Today");
dt.Columns.Add("Addr1");
dt.Columns.Add("Addr2");
dt.Columns.Add("PreferContact");
dt.Columns.Add("TenantName");
//......
DataRow nr = dt.NewRow();
nr["Date"] = DateTime.Now.ToString("dd/MM/yyyy");
nr["Today"] = DateTime.Now.ToString("dd/MM/yyyy");
//......
dt.Rows.Add(nr);
string sourceFile = "c:\my_template.docx"; //this is where you store your template
string filePath = "c:\final.docx"; //this is where your result file locate
Mailmerge(sourceFile, filePath, nr, dt.Columns);
Your template(c:\my_template.docx) will be just like normal .docx file, and you need to specify your fields in it:
<field>
So, your template(c:\my_template.docx) should be like:
<Today>
<DebtorName>
<DebtorADDR>
<DebtorEmail>
Dear <Dear>,
Congratulations on yourr property <PlanNo> <BuildAddress>. Your unit number is <LotNo> ...............
In addition, if some of your fields contain line breaks, use this:
nr["Address"] = my_address_text_contains_line_breaks.Replace(Environment.NewLine, "MS_Doc_New_Line");
This is quite simple by using Microsoft.Office.Interop.Word. Here is a simple step by step tutorial on how to do this.
The code to replace a mergefield with a string is like this:
public static void TextToWord(string pWordDoc, string pMergeField, string pValue)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Word.Application oWord = new Word.Application();
Word.Document oWordDoc = new Word.Document();
oWord.Visible = true;
Object oTemplatePath = pWordDoc;
oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
foreach (Word.Field myMergeField in oWordDoc.Fields)
{
Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
if (fieldName == pMergeField)
{
myMergeField.Select();
oWord.Selection.TypeText(pValue);
}
}
}
}
originally posted here and here
In case you wish to use a dictionary to replace many fields at once use the code below:
public static void TextToWord(string pWordDoc, Dictionary<string, string> pDictionaryMerge)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Microsoft.Office.Interop.Word.Application oWord = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document oWordDoc = new Microsoft.Office.Interop.Word.Document();
oWord.Visible = true;
Object oTemplatePath = pWordDoc;
oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
foreach (Microsoft.Office.Interop.Word.Field myMergeField in oWordDoc.Fields)
{
Microsoft.Office.Interop.Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
foreach (var item in pDictionaryMerge)
{
if (fieldName == item.Key)
{
myMergeField.Select();
oWord.Selection.TypeText(item.Value);
}
}
}
}
}
I am also using the same thing but I have more complexity. I have to check the if condition also. In word template file
{ IF «Installment» = Monthly "then the table will appear" "nothing to show" }
when I use the above code shared in the answer. and for if condition in c# I have written
Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text.Trim();
if (fieldText.ToUpper().StartsWith("IF"))
{
myMergeField.UpdateSource();}
so the output is like
{ IF Monthly = Monthly "then table will appear" "nothing to show" }
but the desired output is only "then the table will appear".

set multiple parameter in recursive c#

when I make 2 parameters. when the cursor on highlight ahref not getting value, as the first parameter? but always get the value of its parent.
What should I do with my code below:
please help correct the errors / shortcomings of my code.
private string LoadNavigasi(string kodeJabatan, ref int countLoop)
{
if (kodeJabatan == null)
kodeJabatan = "001";
DataSet ds = RunQuery("Select KodePosition,NamaPosition,Parent from Position where KodePosition = '" + kodeJabatan + "'");
string temp = string.Empty;
string tempP = string.Empty;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
var kode = ds.Tables[0].Rows[i][0].ToString();
var nama = ds.Tables[0].Rows[i][1].ToString();
var parent = ds.Tables[0].Rows[i][2].ToString();
if (parent == "")
parent = null;
temp = string.Format("{0}", nama);
tempP = string.Empty;
countLoop++;
if (parent != null)
{
tempP = string.Format("{0}", LoadNavigasi(parent, ref countLoop));
temp = string.Format("{1}<ul><li>{0}", temp, tempP);
}
else
{
temp = string.Format("{0}", temp);
}
return temp;
}
return temp;
}
I'm not sure if it helps but I simplify your code to what it's actually doing.
private string LoadNavigasi(string kodeJabatan)
{
if (kodeJabatan == null)
kodeJabatan = "001";
DataSet ds = RunQuery("Select KodePosition,NamaPosition,Parent from Position where KodePosition = '" + kodeJabatan + "'");
var kode = ds.Tables[0].Rows[0][0].ToString();
var nama = ds.Tables[0].Rows[0][1].ToString();
var parent = ds.Tables[0].Rows[0][2].ToString();
string temp = string.Format("<a href=?Kode={0}&Name={1}>{1}</a>", kode, nama);
if (string.IsNullOrEmpty(parent))
{
string tempP = LoadNavigasi(parent);
temp = string.Format("{1}<ul><li>{0}", temp, tempP);
}
return temp;
}
You mention something about your second parameter in the line
temp = string.Format("{0}", nama);
The second parameter is nama but I don't understand what's wrong with it.

Open XML Word C# - Split into Two Columns

I was wondering how would it be possible to split the word document into two columns. The reason why I want to do this is because I want to be able to fit all of the information on one page.
Thank you so much for your help and time!
My Code
using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();
mainPart.Document = new Document();
var margin_size = 100;
PageMargin pargeMargins = new PageMargin();
pargeMargins.Top = margin_size;
pargeMargins.Bottom = margin_size;
SectionProperties sectionProps = new SectionProperties();
sectionProps.Append(pargeMargins);
Body body = mainPart.Document.AppendChild(new Body());
body.Append(sectionProps);
ParagraphProperties paragraphProperties = new ParagraphProperties
(
//new ParagraphStyleId() { Val = "No Spacing" },
new SpacingBetweenLines() { After = "0" }
);
Paragraph para_main = body.AppendChild(new Paragraph(paragraphProperties));
// Creating the Header where the Serial Number will exist
// Serial Number
Run run_mainHeader = para_main.AppendChild(new Run());
RunProperties runProp_mainHeader = new RunProperties(); // Create run properties.
FontSize size_mainHeader = new FontSize();
size_mainHeader.Val = new StringValue("48");
runProp_mainHeader.Append(size_mainHeader);
run_mainHeader.Append(runProp_mainHeader); // Append all of the properties
run_mainHeader.Append(new Text("S/N: " + sn));
// Serial Barcode
Run run_barcode = para_main.AppendChild(new Run());
RunProperties runProp_barcode = new RunProperties(); // Create run properties.
RunFonts runFontMain_barcode = new RunFonts(); // Create font
runFontMain_barcode.Ascii = "Code39AzaleaNarrow1"; // Specify font family
FontSize size_barcode = new FontSize();
size_barcode.Val = new StringValue("48");
runProp_barcode.Append(runFontMain_barcode);
runProp_barcode.Append(size_barcode);
run_barcode.PrependChild<RunProperties>(runProp_barcode);
sn = sn.ToUpper(); // Sets all the values to uppercase to be a barcode format
run_barcode.AppendChild(new Text("*" + sn + "*"));
run_barcode.AppendChild(new Break());
// Tube Type
Run run_tubetype = para_main.AppendChild(new Run());
RunProperties runProp_tubetype = new RunProperties(); // Create run properties.
FontSize size_tubetype = new FontSize();
size_tubetype.Val = new StringValue("38");
runProp_tubetype.Append(size_tubetype);
run_tubetype.Append(runProp_tubetype); // Append all of the properties
run_tubetype.Append(new Text("Tube Type: " + forms[0].TubeType + " "));
//run_tubetype.Append(new Break());
// Tube Barcode
Run run_barcode_tube = para_main.AppendChild(new Run());
RunProperties runProp_barcode_tube = new RunProperties(); // Create run properties.
RunFonts runFontMain_barcode_tube = new RunFonts(); // Create font
runFontMain_barcode_tube.Ascii = "Code39AzaleaNarrow1"; // Specify font family
FontSize size_barcode_tube = new FontSize();
size_barcode_tube.Val = new StringValue("48");
runProp_barcode_tube.Append(runFontMain_barcode_tube);
runProp_barcode_tube.Append(size_barcode_tube);
run_barcode_tube.PrependChild<RunProperties>(runProp_barcode_tube);
sn = sn.ToUpper(); // Sets all the values to uppercase to be a barcode format
run_barcode_tube.AppendChild(new Text("*" + forms[0].TubeType + "*"));
run_barcode_tube.AppendChild(new Break());
// Goes through all of the forms
foreach (var form in forms)
{
// Set up a header per form
Run run_header = para_main.AppendChild(new Run());
RunProperties runProp_formHeader = new RunProperties();
Bold bold = new Bold();
Underline ul = new Underline() { Val = DocumentFormat.OpenXml.Wordprocessing.UnderlineValues.Single };
FontSize size_formHeader = new FontSize();
size_formHeader.Val = new StringValue("24");
runProp_formHeader.Append(size_formHeader);
runProp_formHeader.Append(bold);
runProp_formHeader.Append(ul);
run_header.AppendChild(new RunProperties(runProp_formHeader));
//run_header.AppendChild(new RunProperties(new Bold(), new Underline()));
string username = form.Username;
string proces_header = form.HeaderTitle;
run_header.AppendChild(new Text(proces_header));
run_header.AppendChild(new Break());
// Goes through all of the fields that each form contains.
for (int i = 0; i < form.FieldList.Count; i++)
{
// Do not need to print out user or serial for each form.
if (!(form.FieldList[i].Token == "SNT"))
{
Run run_data = para_main.AppendChild(new Run());
if (form.FieldList[i].Default)
{
run_data.AppendChild(new Text(form.FieldList[i].Label));
}
else
{
run_data.AppendChild(new Text(form.FieldList[i].Label + " " + form.FieldList[i].Spec + form.FieldList[i].Value));
}
run_data.AppendChild(new Break());
}
}
}
mainPart.Document.Save();
wordDoc.Close();
return "Success";
}
Currently the code prints out everything top-down on one column. And I want it with two columns
You can two or how many columns you want using the Columns Class for the SectionProperties and ParagraphProperties Class
http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.columns(v=office.14).aspx
http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.paragraphproperties(v=office.14).aspx
http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.sectionproperties(v=office.14).aspx
This should do it:
// Add a new main document part.
package.AddMainDocumentPart();
// Create the Document DOM.
package.MainDocumentPart.Document = new Document();
Body bd = package.MainDocumentPart.Document.Body = new Body();
//write a first paragraph on two columns
var paragrap1 = new Paragraph();
var paragraphSectionProperties = new ParagraphProperties(new SectionProperties());
var paragraphColumns = new Columns();
paragraphColumns.EqualWidth = true;
paragraphColumns.ColumnCount = 2;
paragraphSectionProperties.Append(paragraphColumns);
paragrap1.Append(paragraphSectionProperties);
paragrap1.Append(new Run(new Text(str)));
bd.AppendChild(paragrap1);
//write another paragraph without paragraph properties
bd.Append(new Paragraph(new Run(new Text(str))));
//set the body properties default three columns
var sectionProperties = new SectionProperties();
var columns = new Columns();
columns.EqualWidth = true;
columns.ColumnCount = 3;
sectionProperties.Append(columns);
bd.Append(sectionProperties);
package.MainDocumentPart.Document.Save();
You can do it for the complete document with this code:
var sectionProperty = document.Body.Descendants<SectionProperties>().First();
var paragraphColumns = new Columns {EqualWidth = true, ColumnCount = 2};
sectionProperty.Append(paragraphColumns);
Try with..
Word.Application WordApp = new Word.Application();
Word.Document BaseDoc = default(Word.Document);
Word.Document DestDoc = default(Word.Document);
int intNumberOfPages = 0;
string intNumberOfChars = null;
int intPage = 0;
//Word Constants
const var wdGoToPage = 1;
const var wdStory = 6;
const var wdExtend = 1;
const var wdCharacter = 1;
//Show WordApp
WordApp.ShowMe();
//Load Base Document
BaseDoc = WordApp.Documents.Open(Filename);
BaseDoc.Repaginate();
//Loop through pages
intNumberOfPages = BaseDoc.BuiltInDocumentProperties("Number of Pages").value;
intNumberOfChars = BaseDoc.BuiltInDocumentProperties("Number of Characters").value;
for (intPage = 1; intPage <= intNumberOfPages; intPage++) {
if (intPage == intNumberOfPages) {
WordApp.Selection.EndKey(wdStory); }
else {
WordApp.Selection.GoTo(wdGoToPage, 2);
Application.DoEvents();
WordApp.Selection.MoveLeft(Unit = wdCharacter, Count = 1);
}
Application.DoEvents();
WordApp.Selection.HomeKey(wdStory, wdExtend);
Application.DoEvents();
WordApp.Selection.Copy();
Application.DoEvents();
//Create New Document
DestDoc = WordApp.Documents.Add;
DestDoc.Activate();
WordApp.Selection.Paste();
DestDoc.SaveAs(NewFileName + intPage.ToString + ".doc");
DestDoc.Close();
DestDoc = null;
WordApp.Selection.GoTo(wdGoToPage, 2);
Application.DoEvents();
WordApp.Selection.HomeKey(wdStory, wdExtend);
Application.DoEvents();
WordApp.Selection.Delete();
Application.DoEvents();
}
BaseDoc.Close(false);
BaseDoc = null;
WordApp.Quit();
WordApp = null;

Categories