OpenOffice MailMerge probléma

OpenOffice MailMerge probléma

Több hetes kutatás után sem tudtam megoldani a Mailmerge-et OpenOffice-, illetve LobreOffice-ban. A dokumentáció nem teljes, a fórumokon feltett kérdésekre pedig vagy nem válaszolnak, vagy egy számtalan helyen megtalálható hibás kódot adnak meg mintapéldának. (A kód tartalmazza kommentben, hogy egyébként nem működik…) Így hát kerülőutat kellett keresnem, hogyan tudnám megvalósítani ezt saját eszközökkel. Meg is találtam, a megoldást az alábbiakan olvashatjátok.

Az odt kiterjesztésű fájlok tulajdonképpen zippelt xml-ek:

Értelemszerűen az office fájl tartalma a content.xml-ben, a stílusok a styles.xml-ben vannak. A mailMerge-hez tehát nem kell mást tennünk, mint kikeresni az adatmezőket a content.xml-ben és lecserélni a hozzárendelt mezőtartalomra. Ehhez egy CSV fájlt használok adatforrásként, mint az OpenOffice is, amikor a „körlevéltündér”-el végezzük el a MailMerge-öt. Az adatmező hivatkozások tag-ek között vannak, ezt kell teljesen lecserélni a mezőértékekre a content.xml-ben. A ZIP-hez a DotNetZip-et használtam, innen letölthető a forráskód is.

Az alábbi (Nem túl bonyolult.) kód magáért beszél, de azért igyekeztem bőbeszédűen kommentelni is… 

///
/// Saját mailmerge rutin.
/// Lépések:
/// 1. Zip-el kibontom az ODT fájlt.
/// 2. Kikeresem benne a content.xml-t.
/// 3. A CSV formátumú adatfájlból (Amely egy fejléc és egy adatsort tartalmaz.) 
/// kiolvasom a mezőneveket és lecserélem a hozzá tartozó adatokra a content.xml-ben.
/// Az adatmező hivatkozások tag-ek között vannak, ezt teljesen le kell cserélni.
/// 4. Frissítem a content.xml-t és mentwm a zip-et.
///
///A célfájl neve.
private void MailMerge(string mergedfilename)
{
    try
    {
        // A template-et átmásolom a célfájl-ba, de előtte megnézem, hogy létezik-e?
        if (File.Exists(mergedfilename))
        {
            // Ha létezik letörlöm, mert újat hozok létre.
            File.Delete(mergedfilename);
        }
        // A template file nevét az osztály egyik property-je tartalmazza
        File.Copy(TemplateFileName, mergedfilename);
 
        // Unzip és merge
        using (ZipFile zip = ZipFile.Read(mergedfilename))
        {
            // Flag a mentés befejezéséhez
            zipFinished = false;
            zip.SaveProgress += zip_SaveProgress;
            foreach (ZipEntry entry in zip.Entries)
            {
                //Rákeresek a content.xml-re.
                if (entry.FileName == "content.xml")
                {
                    //Megnyitom stream-ként
                    var s = entry.OpenReader();
 
                    //Kiolvasom az adatokat
                    byte[] rdata = new byte[s.Length];
                    s.Read(rdata, 0, rdata.Length);
 
                    //Stringgé alakítom
                    string text = System.Text.Encoding.Default.GetString(rdata);
 
                    //Megnyitom az adatfájlt
                    StreamReader sr = new StreamReader(_mailMergeDataSourceFromFile);
                    if (sr != null)
                    {
                        string fejlec = sr.ReadLine();
                        string data = sr.ReadLine();
                        sr.Close();
 
                        string[] fejlecek = fejlec.Split('\t');
                        string[] adatok = data.Split('\t');
 
 
                        // Feltételezem, hogy az adattábla neve a fájl neve is.
                        // Az adatok hozzárendelésénél ez az alapértelmezett az OpenOffice/LibreOffice-ban
                        string dataname = Path.GetFileName(_mailMergeDataSourceFromFile);
                        dataname = dataname.Remove(dataname.IndexOf(Path.GetExtension(dataname)));
 
                        //Kicserélem az összes mezőt
                        for (int i = 0; i < fejlecek.Count(); i++)
                        {
                            string _search = fejlecek[i].Replace("\"", "");
                            string _replace = adatok[i].Replace("\"", "");
 
                            string mit = String.Format("<{0}>", _search, dataname);
                            text = text.Replace(mit, _replace);
                        }
                    }
 
                    //Visszaalakítom byte tömbbé
                    byte[] wdata = new byte[text.Length];
                    wdata = System.Text.Encoding.UTF8.GetBytes(text);
 
                    // Frissítem a content.xml-t és mentwm a zip-et.
                    zip.UpdateEntry(entry.FileName, wdata);
                    zip.Save();
 
                    // Megvárom a mentés végét.
                    while (!zipFinished)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                    break;
                }
            }
        }
    }
    catch (System.Exception ex)
    {
        // Tovább dobom az exceptiont saját message-el.
        throw new System.Exception("A MailMerge sikertelen! " + ex.Message);
    }
}
 
///
/// Itt viszgálom meg, hogy befejeződött-e a zip mentése.
///
///
///
void zip_SaveProgress(object sender, SaveProgressEventArgs e)
{
    if (e.EventType == ZipProgressEventType.Saving_Completed)
    {
        zipFinished = true;
    }
}

 

Sok sikert!

Sziklai Frigyes