I want to read a file with this code but after 682 times i get this error:
Exception of type 'System.OutOfMemoryException' was thrown.
System.IO.StreamReader file = new System.IO.StreamReader(scanpad[lusteller]);
scanpad is an array with the filepaths and lusteller is counter for it.
Scanpad excists 11207 files.
I have also have looked en there is a file on place 682
Anyone a solution?
Here the full version of my code
using (StreamReader file = new System.IO.StreamReader(scanpad[lusteller]))
{
//do stuff
lengte = bestandsnaam.Length;
lengte = lengte - 13;
controller = bestandsnaam.Remove(lengte, 13); // controllertype uit naam halen
do
{
rij = file.ReadLine();
if (rij != null) //error op volgende lijn vermijden
{
if (rij.StartsWith("0") || rij.StartsWith("1") || rij.StartsWith("2") || rij.StartsWith("3"))
{
rijcheck = true;
}
teller = teller + 1;
if (teller > 10)
{
if (rijcheck == true) // rij is datumlijn
{
string[] split = rij.Split(' ');
foutinformatie[0, index] = type; //type ophalen
foutinformatie[3, index] = controller; //controllernaam ophalen
foutinformatie[1, index] = split[0]; //datum ophalen
foutinformatie[2, index] = split[1]; //tijd ophalen
foutinformatie[4, index] = split[2]; //foutcode ophalen
foutinformatie[5, index] = split[5]; //foutteller ophalen
if (controller.StartsWith("MPU") == true)
{
lusarraygraad = 5;
while (lusarraygraad < 360)
{
if (graadmpu[0, lusarraygraad] == split[2])
{
try
{
graad = graadmpu[1, lusarraygraad];
foutinformatie[7, index] = graad;
}
catch
{
}
lusarraygraad = lusarraygraad + 499;
graadgevonden = true;
}
lusarraygraad = lusarraygraad + 1;
}
foutinformatie[7, index] = graad;
if (graadgevonden == false)
{
foutinformatie[7, index] = "";
}
graadgevonden = false;
}
//////////////////////////////////////////////////////////////////////////
if (controller.StartsWith("AAUX") == true)
{
lusarraygraad = 4;
while (lusarraygraad < 30)
{
if (graadaaux[0, lusarraygraad] == split[2])
{
try
{
graad = graadaaux[1, lusarraygraad].ToString();
foutinformatie[7, index] = graad;
}
catch
{
}
lusarraygraad = lusarraygraad + 499;
graadgevonden = true;
}
lusarraygraad = lusarraygraad + 1;
}
foutinformatie[7, index] = graad;
if (graadgevonden == false)
{
foutinformatie[7, index] = "";
}
graadgevonden = false;
}
if (controller.StartsWith("ACTRL") == true)
{
lusarraygraad = 6;
while (lusarraygraad < 85)
{
if (graadactrl[0, lusarraygraad] == split[2])
{
try
{
graad = graadactrl[1, lusarraygraad].ToString();
foutinformatie[7, index] = graad;
}
catch
{
}
lusarraygraad = lusarraygraad + 499;
graadgevonden = true;
}
lusarraygraad = lusarraygraad + 1;
}
foutinformatie[7, index] = graad;
if (graadgevonden == false)
{
foutinformatie[7, index] = "";
}
graadgevonden = false;
}
try
{
telleromschrijving = 6;
informatie = "";
while (split[telleromschrijving] != " ")
{
informatie = informatie + " " + split[telleromschrijving];
telleromschrijving = telleromschrijving + 1;
}
}
catch
{
foutinformatie[6, index] = informatie; //foutteller ophalen
}
rijcheck = false;
rij = file.ReadLine();
while (varcheck < 40)
{
// rij met eerste variable
if (rij != "")
{
variable[indexlokaal, varteller] = rij;
foutinformatie[varteller + 8, index] = variable[indexlokaal, varteller] = rij;
varteller = varteller + 1;
rij = file.ReadLine();
}
else
{
foutinformatie[varteller + 8, index] = " ";
varteller = varteller + 1;
}
varcheck = varcheck + 1;
}
varcheck = 0;
varteller = 0;
indexlokaal = indexlokaal + 1;
index = index + 1;
}
}
}
}
while (rij != null);
file.Close();
file.Dispose();
}
I imagine 682 is just a number where you happen to be running out of memory, not a special number. you should encapsulate your streamreader into
using(StreamReader file = new System.IO.StreamReader(scanpad[lusteller]))
{
//do stuff
}
This way, your streamreader is disposed of after being used, clearing memory
EDIT FOR UPDATE
Inside your streamreader you also have
rij = file.ReadLine();
while (varcheck < 40)
{
// rij met eerste variable
if (rij != "")
{
variable[indexlokaal, varteller] = rij;
foutinformatie[varteller + 8, index] = variable[indexlokaal, varteller] = rij;
varteller = varteller + 1;
rij = file.ReadLine();
}
but you are not checking if ReadLine is returning null again, looking at
http://msdn.microsoft.com/en-GB/library/system.io.streamreader.readline.aspx
This can also cause a outofmemory exception as your stream has reached null and yet you have continued onwards
It all depends on what you do with the StreamReader.
First of all you need to dispose it, but I don't believe it's the issue as the GC would have collected it before running out of memory (unless you also hold a reference to it).
If you use something like "ReadToEnd" and the content of the files is large you hit Large Object Heap with the strings created (and if you manipulate them by creating sub-string it can get worse).
After a while the heap becomes fragmented so you run out of memory because it is unable to find large enough memory chunk for your request.
Well, that's my guess with little info into your code, good luck.
Try use Using:(disposed memory after read)
using(System.IO.StreamReader file = new System.IO.StreamReader(scanpad[lusteller]))
{
}
Related
I need to compress more folder at same time in different archivie to goes more quikly.
I tried to use a main backgroundworker and from this I did a for cycle to start other backgroundworker for each folder. I notice that the backgroundworker starts all at same time but not works together what is the best way to do a parallel archive?what you suggest?
to create the archive I use the zipforge library
DoWork of the main backgroundworker
if (Directory.Exists(destination))
{
if (MessageBox.Show("", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
{
goto EXIT_UTENTE;
}
else
{
bool finish = false;
int j = 1;
string dest_appoggio = destination;
do
{
dest_appoggio = destination + "_" + j;
if (Directory.Exists(dest_appoggio))
{
j++;
}
else
{
destination = dest_appoggio;
dataprogressiva = data + "_" + j;
finish = true;
}
}
while (finish == false);
}
}
destinationdefault = destination;
var row_list1 = GetDataGridRows(dgwRobot);
int riga = -1;
foreach (DataGridRow single_row1 in row_list1)
{
bool rowselected = false;
single_row1.Dispatcher.Invoke(new Action(() => { rowselected = single_row1.IsSelected; }));
if (rowselected == true)
{
riga = single_row1.GetIndex();
var robotProcessed = false;
while (!robotProcessed)
{
for (var threadNum = 0; threadNum < MaxBackupContemporanei; threadNum++)
{
if (!threadArray[threadNum].IsBusy)
{
threadArray[threadNum].RunWorkerAsync(riga);
robotProcessed = true;
break;
}
}
}
}
Thread.Sleep(500);
}
bool bwTerminati = false;
while (!bwTerminati)
{
for (var threadNum = 0; threadNum < MaxBackupContemporanei; threadNum++)
{
if (threadArray[threadNum].IsBusy)
{
bwTerminati = false;
threadNum = MaxBackupContemporanei;
}
else
{
bwTerminati = true;
}
}
}
I get this error. Later I searched and found out the reason of illegal characters in my XML and its solution. But I don't have the access to edit any of these files. My job is to read and fetch the tag value, attribute value and similar stuff. SO I can't replace the binary characters with escapes like '\x01' with . Also I tried to include CheckCharacters =false in XMLreader settings. It doesn't take this. Still it is throwing the same error.
Is it not possible to fix in XMLreader? I read about XMLtextReader. It can skip the exception. But already I have coded for all my features using XMLreader. It would be good if I can find a solution for this. Otherwise I would have to change all my code.
My code:
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
var filenames = System.IO.Directory
.EnumerateFiles(textBox1.Text, "*.xml", System.IO.SearchOption.AllDirectories)
.Select(System.IO.Path.GetFullPath);
foreach (var f in filenames)
{
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[#"X1.DTD"] = #"\\location\X1.DTD";
resolver.DtdFileMap[#"R2.DTD"] = #"\\location\X2.DTD";
resolver.DtdFileMap[#"R5.DTD"] = #"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(f, settings);
while (doc.Read())
{
if ((doc.NodeType == XmlNodeType.Element) && (doc.Name == "ap"))
{
if (doc.HasAttributes)
{
String fin = doc.GetAttribute("ap");
if (fin == "no")
{
String[] array = new String[10000];
array[i] = (f);
File.AppendAllText(#"\\location\NAPP.txt", array[i] + Environment.NewLine);
i++;
}
else
{
String[] abs = new String[10000];
abs[i] = (f);
File.AppendAllText(#"\\location\APP.txt", abs[i] + Environment.NewLine);
i++;
}
}
}
}
}
MessageBox.Show("Done");
}
This is a very simple example of character "filter" that will replae the 0x06 character with a space:
public class MyStreamReader : StreamReader {
public MyStreamReader(string path)
: base(path) {
}
public override int Read(char[] buffer, int index, int count) {
int res = base.Read(buffer, index, count);
for (int i = 0; i < res; i++) {
if (buffer[i] == 0x06) {
buffer[i] = ' ';
}
}
return res;
}
}
You use it this way:
using (var sr = new MyStreamReader(f)) {
var doc = XmlReader.Create(sr, settings);
Note that it's very simple because it's replacing a character (the 0x06) with another character of the same "length" (the space). If you wanted to replace a character with a "sequence" of characters (to escape it), it would get more complex (not impossible, 30 minutes of work difficult)
(I have checked and it seems the XmlTextReader only uses that method and not the Read() method)
As always, when a programmer tells you 30 minutes, it means 0 minutes or 2 hours :-)
This is the "more complex" ReplacingStreamReader:
/// <summary>
/// Only the Read methods are supported!
/// </summary>
public class ReplacingStreamReader : StreamReader
{
public ReplacingStreamReader(string path)
: base(path)
{
}
public Func<char, string> ReplaceWith { get; set; }
protected char[] RemainingChars { get; set; }
protected int RemainingCharsIndex { get; set; }
public override int Read()
{
int ch;
if (RemainingChars != null)
{
ch = RemainingChars[RemainingCharsIndex];
RemainingCharsIndex++;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
}
else
{
ch = base.Read();
if (ch != -1)
{
string replace = ReplaceWith((char)ch);
if (replace == null)
{
// Do nothing
}
else if (replace.Length == 1)
{
ch = replace[0];
}
else
{
ch = replace[0];
RemainingChars = replace.ToCharArray(1, replace.Length - 1);
RemainingCharsIndex = 0;
}
}
}
return ch;
}
public override int Read(char[] buffer, int index, int count)
{
int res = 0;
// We leave error handling to the StreamReader :-)
// We handle only "working" parameters
if (RemainingChars != null && buffer != null && index >= 0 && count > 0 && index + count <= buffer.Length)
{
int remainingCharsCount = RemainingChars.Length - RemainingCharsIndex;
res = Math.Min(remainingCharsCount, count);
Array.Copy(RemainingChars, RemainingCharsIndex, buffer, index, res);
RemainingCharsIndex += res;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
if (res == count)
{
return res;
}
index += res;
count -= res;
}
while (true)
{
List<char> sb = null;
int res2 = base.Read(buffer, index, count);
if (res2 == 0 || ReplaceWith == null)
{
return res;
}
int j = 0;
for (int i = 0; i < res2; i++)
{
char ch = buffer[index + i];
string replace = ReplaceWith(ch);
if (sb != null)
{
if (replace == null)
{
sb.Add(ch);
}
else
{
sb.AddRange(replace);
}
}
else if (replace == null)
{
buffer[j] = ch;
j++;
}
else if (replace.Length == 1)
{
buffer[j] = replace[0];
j++;
}
else if (replace.Length == 0)
{
// We do not advance
}
else
{
sb = new List<char>();
sb.AddRange(replace);
}
}
res2 = j;
if (sb != null)
{
int res3 = Math.Min(sb.Count, count - res2);
sb.CopyTo(0, buffer, index + res2, res3);
if (res3 < sb.Count)
{
RemainingChars = new char[sb.Count - res3];
RemainingCharsIndex = 0;
sb.CopyTo(res3, RemainingChars, 0, RemainingChars.Length);
}
res += res3;
}
else
{
res2 = j;
// Can't happen if sb != null (at least a character must
// have been added)
if (res2 == 0)
{
continue;
}
}
res += res2;
return res;
}
}
}
Use it like:
using (var sr = new ReplacingStreamReader(f))
{
sr.ReplaceWith = x =>
{
return x == 0x6 ? " " : null;
// return x == '.' ? " " : null; // Replace all . with
};
var doc = XmlReader.Create(sr, settings);
Be aware that the ReplacingStreamReader doesn't "know" which part of the xml it is modifying, so rarely a "blind" replace is ok :-) Other than this limitation, you can replace any character with any string (null in the ReplaceWith means "keep the current character", equivalent to x.ToString() in the example given. Returning string.Empty is valid, means remove the current character).
The class is quite interesting: it keeps a char[] RemainingChars with the chars that have been read (and filtered by ReplaceWith) but that haven't been returned by a Read() method because the passed buffer was too much small (the ReplaceWith method could "enlarge" the read string, making it too much big for the buffer!). Note that sb is a List<char> instead of a StringBuilder. Probably using one or the other would be nearly equivalent, code-wise.
You could first read the content into a string replace (escape) the content, and then load it into a XmlReader:
foreach (var f in filenames) {
string text;
using (StreamReader s = new StreamReader(f,Encoding.UTF8)) {
text = s.ReadToEnd();
}
text = text.Replace("\x01",#""); //replace the content
//load some settings
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[#"X1.DTD"] = #"\\location\X1.DTD";
resolver.DtdFileMap[#"R2.DTD"] = #"\\location\X2.DTD";
resolver.DtdFileMap[#"R5.DTD"] = #"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(text, settings);
//perform processing task
//...
}
It's fairly straight-forward to add a TextField using ABCPDF:
public FormField AddTextField(string inRect, string inName, string inText)
{
int fieldId = mDoc.AddObject("<</Type /Annot /Subtype /Widget /F 4 /FT /Tx /Ff 4096 /Q 1>>");
mDoc.SetInfo(fieldId, "/V:Text", inText);
RegisterField(fieldId, inName, inRect);
return new FormField(fieldId, mDoc);
}
With this as the implementation:
FormField text = AddTextField("40 530 300 580", "TextField1", "Hello World!");
text.DefaultAppearance = "/TimesRoman 36 Tf 0 0 1 rg";
text.BorderColor = "0 0 0";
text.FillColor = "220 220 220";
text.TextAlign = "Left";
If I need to add two fields that have the same name, it's a little more complex:
public int AddGroupField(FormField[] inKids, string inName, string inValue)
{
if (inKids.Length == 0)
throw new Exception("Cannot have a group field with no kids");
string ft = null, dv = null;
int fieldId = mDoc.AddObject("<< /Kids [] >>");
foreach (FormField kid in inKids)
{
mDoc.SetInfo(fieldId, "/Kids[]:Ref", kid.Id.ToString());
mDoc.SetInfo(kid.Id, "/Parent:Ref", fieldId);
if (ft == null)
ft = mDoc.GetInfo(kid.Id, "/FT");
if (dv == null)
dv = mDoc.GetInfo(kid.Id, "/DV");
mDoc.SetInfo(kid.Id, "/FT:Del", "");
mDoc.SetInfo(kid.Id, "/V:Del", "");
mDoc.SetInfo(kid.Id, "/DV:Del", "");
}
mDoc.SetInfo(fieldId, "/FT", ft);
mDoc.SetInfo(fieldId, "/T:Text", inName);
mDoc.SetInfo(fieldId, "/V:Text", inValue);
if (dv != null)
mDoc.SetInfo(fieldId, "/DV:Text", dv);
int eid = mDoc.GetInfoInt(mDoc.Root, "/AcroForm:Ref");
mDoc.SetInfo(eid, "/Fields*[]:Ref", fieldId);
return fieldId;
}
With this as the implementation:
FormField[] kids = new FormField[2];
kids[0] = AddTextField("40 230 300 280", null, null);
kids[1] = AddTextField("40 170 300 220", null, null);
int id = AddGroupField(kids, "TextField1", "Hello World!");
However, I'm having issues with adding a TextField to a PDF where a TextField already exists with that same name. So, for example, if my PDF already has a field named "TextField1" and then I want to add another field with that same name, none of the above implementations will work.
I was able to get the answer from ABCPDF support. And as you can see, it's not exactly a simple process. I'm not sure anyone could just figure this out on their own without spending months and months of research on the PDF spec and the ABCPDF product.
public FormField AddTextField(string inRect, string inName, string inText)
{
bool fieldAlreadyExists = mDoc.Form[inName] != null;
int fieldId = mDoc.AddObject("<</Type /Annot /Subtype /Widget /F 4 /FT /Tx /Ff 4096 /Q 1>>");
mDoc.SetInfo(fieldId, "/V:Text", inText);
RegisterField(fieldId, inName, inRect);
var field = new FormField(fieldId, mDoc);
if (fieldAlreadyExists)
{
InteractiveForm form = new InteractiveForm(mDoc);
form.AddFieldIntoExistingGroup(field, true);
}
return field;
}
private bool AddFieldIntoExistingGroup(FormField field, bool refreshForm)
{
bool duplicatesFound = false;
int acroFormID = mDoc.GetInfoInt(mDoc.Root, "/AcroForm:Ref");
int parentID = mDoc.GetInfoInt(field.Id, "/Parent:Ref");
ArrayAtom kids;
if (parentID > 0)
{
kids = mDoc.ObjectSoup.Catalog.Resolve(Atom.GetItem(mDoc.ObjectSoup[parentID].Atom, "Kids")) as ArrayAtom;
}
else
{
kids = mDoc.ObjectSoup.Catalog.Resolve(Atom.GetItem(mDoc.ObjectSoup[acroFormID].Atom, "Fields")) as ArrayAtom;
}
Dictionary<string, List<IndirectObject>> items = new Dictionary<string, List<IndirectObject>>();
for (int i = 0; i < kids.Count; i++)
{
IndirectObject io = mDoc.ObjectSoup.Catalog.ResolveObj(kids[i]);
if (io == null)
{
continue; // shouldn't really happen
}
string name = mDoc.GetInfo(io.ID, "/T:Text");
if (!items.ContainsKey(name))
{
items[name] = new List<IndirectObject>();
}
items[name].Add(io);
}
foreach (KeyValuePair<string, List<IndirectObject>> pair in items)
{
if (pair.Value.Count > 1)
{
duplicatesFound = true;
// shift field down to be a child of a new field node
int id = mDoc.AddObject("<< >>");
if (parentID > 0)
{
mDoc.SetInfo(parentID, "/Kids[]:Ref", id);
mDoc.SetInfo(id, "/Parent:Ref", parentID);
}
else
{
mDoc.SetInfo(acroFormID, "/Fields[]:Ref", id);
}
string[] dictEntries = new[] { "/FT", "/T", "/TU", "/Ff", "/V", "/DV" };
foreach (IndirectObject io in pair.Value)
{
foreach (string dictEntry in dictEntries)
{
string val = mDoc.GetInfo(io.ID, dictEntry);
if (!string.IsNullOrEmpty(val))
{
mDoc.SetInfo(id, dictEntry, val);
mDoc.SetInfo(io.ID, dictEntry + ":Del", "");
}
}
ArrayRemoveOneRefAtom(kids, io.ID);
mDoc.SetInfo(id, "/Kids[]:Ref", io.ID);
mDoc.SetInfo(io.ID, "/Parent:Ref", id);
}
}
}
if ((refreshForm) && (duplicatesFound))
{
mDoc.Form.Refresh();
}
return duplicatesFound;
}
private static bool ArrayRemoveOneRefAtom(ArrayAtom array, int id)
{
if (array != null)
{
for (int i = 0; i < array.Count; i++)
{
RefAtom refAtom = array[i] as RefAtom;
if ((refAtom != null) && (refAtom.ID == id))
{
ArrayRemoveAt(array, i);
return true;
}
}
}
return false;
}
private static void ArrayRemoveAt(ArrayAtom array, int index)
{
if (index == 0)
{ // Workaround for bug in some versions of ABCpdf
Atom[] copy = new Atom[array.Count];
array.CopyTo(copy, 0);
array.Clear();
for (int i = 1; i < copy.Length; i++)
array.Add(copy[i]);
}
else
{
array.RemoveAt(index);
}
}
How to display multiple icons on same points in googlemap in .net using goolemap api 3
Below is my code
public void selectTrainings(string strQuery)
{
try
{
clsTblMembers objtblMember = new clsTblMembers();
objtblMember.StrEmail = strQuery.ToString();
DataTable dt = objtblMember.SelectSearch();
if (dt != null)
{
int i;
for (i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i]["Latitude"].ToString() != "" && dt.Rows[i]["Longitude"].ToString() != "")
{
string StrLat = dt.Rows[i]["Latitude"].ToString();
string StrLon = dt.Rows[i]["Longitude"].ToString();
double Numlat;
bool isNumlat = double.TryParse(StrLat, out Numlat);
double Numlon;
bool isNumlon = double.TryParse(StrLon, out Numlon);
if ((isNumlat) && (isNumlon))
{
//coordinates datatype =double;
m1 = new MapControl.MapMarker();
m1.Latitude = Convert.ToDouble(dt.Rows[i]["Latitude"].ToString());
m1.Longitude = Convert.ToDouble(dt.Rows[i]["Longitude"].ToString());
getTraining(Convert.ToInt32(dt.Rows[i]["intId"].ToString()), Convert.ToInt32(dt.Rows[i]["intTypeId"].ToString()), dt.Rows[i]["strCode"].ToString(), dt.Rows[i]["strConductedBy"].ToString(), dt.Rows[i]["dtFromDate"].ToString(), dt.Rows[i]["dtToDate"].ToString(), dt.Rows[i]["strName"].ToString(), dt.Rows[i]["strUC"].ToString(), dt.Rows[i]["strVillage"].ToString());
if (dt.Rows[i]["intTypeId"].ToString() == "1")
{
m1.Title ="CMST - "+ dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/t1.png";
}
else if (dt.Rows[i]["intTypeId"].ToString() == "2")
{
m1.Title = "LMST - " + dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/t2.png";
}
else if (dt.Rows[i]["intTypeId"].ToString() == "3")
{
m1.Title = " Govt.Official Training - " + dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/t3.png";
}
else if (dt.Rows[i]["intTypeId"].ToString() == "4")
{
m1.Title = "Gender Based Violence - " + dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/pg.png";
}
else if (dt.Rows[i]["intTypeId"].ToString() == "5")
{
m1.Title = "Human Rights - " + dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/ph.png";
}
else
{
m1.Title = "Livelihoods Skills Training - " + dt.Rows[i]["strCode"].ToString();
m1.Image = "mapIcons/t4.png";
}
m1.ImageSize1 = 32.0;
m1.ImageSize2 = 37.0;
m1.ImagePoint1 = 0;
m1.ImagePoint2 = 0;
m1.ImagePoint3 = 16.0;
m1.ImagePoint4 = 18.0;
m1.Shadow = "mapIcons/shadow.png";
m1.ShadowSize1 = 51.0;
m1.ShadowSize2 = 37.0;
m1.ShadowPoint1 = 0;
m1.ShadowPoint2 = 0;
m1.ShadowPoint3 = 16.0;
m1.ShadowPoint4 = 18.0;
GoogleMap.Markers.Add(m1);
}
}
}
}
}
catch (Exception ex)
{
}
}
I' have a Project that needs to do a mailmerge, I'm performing this with VSTO. I need to check if all records on the MailMerge.DataSource.DataFields are ok. i'm doing that with this code.
public void verificarPersonas(Word.Document Doc)
{
ThisAddIn ThisAddIn = Globals.ThisAddIn;
List<Personas> miListaPersonas = new List<Personas>();
decimal nRecords = Doc.MailMerge.DataSource.RecordCount;
if (nRecords == 0)
{
cambiarEstado("Empty db or documento does'n prepared for mail merge", false);
}
else
{
string fieldIdentificacion = persParm("Identificacion");
string fieldNombre = persParm("Nombres");
string fieldApellido = persParm("Apellidos");
string fieldEmail = persParm("Email");
string fieldDireccion = persParm("Direccion");
string fieldTelefono = persParm("Telefono");
if (String.IsNullOrEmpty(fieldIdentificacion) || String.IsNullOrEmpty(fieldNombre))
{
cambiarEstado("", false);
return;
}
else
{
for (int i = 1; i <= nRecords; i++)
{
Doc.MailMerge.DataSource.FirstRecord = i;
Doc.MailMerge.DataSource.LastRecord = i;
// Here Allways get the first record
dynamic fields = Doc.MailMerge.DataSource.DataFields;
// ________________________________
Personas personaActual = new Personas();
personaActual.IdPersona = 0;
try
{
personaActual.Identificacion = fields(fieldIdentificacion).value;
personaActual.Nombres = fields(fieldNombre).value;
personaActual.Apellidos = (String.IsNullOrEmpty(fieldApellido) ? "" : fields(fieldApellido).value);
personaActual.Email = (String.IsNullOrEmpty(fieldEmail) ? "" : fields(fieldEmail).value);
personaActual.Direccion = (String.IsNullOrEmpty(fieldDireccion) ? "" : fields(fieldDireccion).value);
personaActual.Telefono = (String.IsNullOrEmpty(fieldTelefono) ? "" : fields(fieldTelefono).value);
miListaPersonas.Add(personaActual);
}
catch (Exception e)
{
cambiarEstado(""+e.Message, false);
return;
}
}
string listaPersonasJson = JsonConvert.SerializeObject(miListaPersonas);
string respuesta = wt.getWebData("Personas", "verificarPersonasVSTO", new { personas = listaPersonasJson });
}
}
}
My problem is that dynamic fields = Doc.MailMerge.DataSource.DataFields; allways get the first record.
How can I do to get datafields for the active record ?
After some hours of research and some tries. get that the fields collection of datasource dont move the pointer when you set FirstRecord and Lastrecord, it must be moved using activerecords, using WdMailMergeActiveRecord enumeration, sonething like this:
int nRecords = Doc.MailMerge.DataSource.RecordCount;
for (int i = 1; i <= nRecords; i++)
{
Doc.MailMerge.DataSource.FirstRecord = i; //It doesn't work
Doc.MailMerge.DataSource.LastRecord = i; // it doesn't work
Doc.MailMerge.DataSource.ActiveRecord = (i == 1 ?
Word.WdMailMergeActiveRecord.wdFirstDataSourceRecord :Word.WdMailMergeActiveRecord.wdNextDataSourceRecord);
Doc.MailMerge.DataSource.ActiveRecord = (i == nRecords ? Word.WdMailMergeActiveRecord.wdLastDataSourceRecord : Doc.MailMerge.DataSource.ActiveRecord);
dynamic fields = Doc.MailMerge.DataSource.DataFields;
}