Копируете лишнюю пустую страницу из выбранного раздела Word Doc?

Я написал следующий код, позволяющий пользователям запрашивать данные на основе документа Word, который будет напечатан, и источника данных (разные системы), где они могут выбрать ИСТОЧНИК1, ИСТОЧНИК2 или ОБА. Данные запрашиваются, помещаются в ODBC DataReader, а затем передаются по циклу для заполнения элемента управления ListView.

Затем я позволяю пользователям выбирать, какие записи они хотят распечатать, и эти записи обрабатываются в выбранный текстовый документ как операция слияния.

Сейчас я пытаюсь сохранить каждую отдельную страницу документа Word (каждую запись слияния) в определенную папку с собственным именем.

КОД:

private void btnSearch_Click(object sender, EventArgs e)
        {
            lvData.Clear();
            string qryCmd = "";

            createColumns();

            switch (cmbLetterType.SelectedIndex)
            {
                case 0:
                    qryCmd = chkSystem("oldAddr");
                    break;
                case 1:
                    qryCmd = chkSystem("newAddr");
                    break;
                case 2:
                    qryCmd = chkSystem("nameChg");
                    break;
            }

            // If the option for BOTH is selected, qryCmd is a long string containing the individual queries for SOURCE1 and SOURCE2.
            // Here I check if a semicolon (;) exists, denoting that there are 2 cmd queries in the string.
            // If so, I split the query calling GetiSeriesData() with the first query string, then assigning qryCmd the second 
            // strings value and continuing processing as normal.
            if (qryCmd.Contains(";"))
            {
                char[] delimitChar = { ';' };
                string[] splitQueries = qryCmd.Split(delimitChar);
                qryCmd = splitQueries[0];
                GetiSeriesData(qryCmd);
                qryCmd = splitQueries[1];
            }

            GetiSeriesData(qryCmd);

            // Display message if no records found.
            if (lvData.Items.Count == 0)
            {
                MessageBox.Show("No records found.");
            }
            lblRecCnt.Text = lvData.Items.Count.ToString();
            this.lvData.CheckBoxes = true;
         }

public void GetiSeriesData(string query)
        {
            OdbcDataReader dr;
            try
            {
                //Set value of system based on table being looked at in ConnectionString
                string sysValue = "";
                if (query.Contains("lib1"))
                {
                    sysValue = "P";
                }
                if (query.Contains("lib2"))
                {
                    sysValue = "N";
                }

                MergeDocLibrary mdl = new MergeDocLibrary();
                dr = mdl.GetData(query);

                Int16 x = 0;
                string gndr = "";

                // Fill ListView Control lvData
                while (dr.Read())
                {
                    lvData.Items.Add(dr["MEMNO"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["NAME"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ADDR1"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ADDR2"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["STATE"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ZIP"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ADDR1"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ADDR2"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_CITY"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_STATE"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ZIP"].ToString().Trim());

                    lvData.Items[x].SubItems.Add(sysValue.ToString().Trim());
                    lvData.Items[x].SubItems.Add(DateTime.Today.ToString("d"));
                    lvData.Items[x].SubItems.Add(dr["SEX"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["LNAME"].ToString().Trim());
                    if (dr["SEX"].ToString().Trim() == "M")
                    {
                        gndr = "Mr.";
                    }
                    else // (dr["SEX"].ToString().Trim() == "F)
                    {
                        gndr = "Ms.";
                    }
                    lvData.Items[x].SubItems.Add(gndr + dr["LNAME"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim() + ", " + dr["STATE"].ToString().Trim() + " " + dr["ZIP"].ToString().Trim());
                    x += 1;
                }

                mdl.closeConn();

            }
            catch (Exception ex)
            {
                MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
            }
            finally
            {

            }
        }

public void OpenAndReview()
    {
        try
        {
            string docSave = @"C:\Users\NAME\Desktop\Test.doc";

        //MergeDocLibrary mdl = new MergeDocLibrary();
        //mdl.mergeDocument(docSource, docLoc);

        // Original Mail Merge Document
        Word.Range rng;
        object start = 0;
        object end = 0;
        Word.Range newWrdRng;
        Word.Application oWord = new Word.Application();
        Word.Document oWrdDoc = new Word.Document();

        // New Document Instance
        Word.Application oNewWord = new Word.Application();
        Word.Document oNewWrdDoc = new Word.Document();

        // Set 'False' in PROD, 'True' in DEV
        oWord.Visible = true;
        oNewWord.Visible = true;
        Object oTemplatePath = docLoc;

        // Open Mail Merge Doc
        oWrdDoc = oWord.Documents.Open(oTemplatePath);

        // Open New Document
        oNewWrdDoc = oNewWord.Documents.Open(docSave);
        Object oMissing = System.Reflection.Missing.Value;

        // Open Mail Merge Datasource
        oWrdDoc.MailMerge.OpenDataSource(docSource, oMissing, oMissing, oMissing,
           oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);

        // Execute Mail Merge
            oWrdDoc.MailMerge.Execute();

            // Set Mail Merge Document as Active Doc
            //oWrdDoc.Activate();

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            MessageBox.Show(oWord.ActiveDocument.Sections.Count.ToString());
            // 3 Records selected gives 4 Sections Counted??
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // Subtract 1 to account for the extra section being counted?

            int docCnt = oWord.ActiveDocument.Sections.Count - 1;

            int cnt = 0;
            while (cnt != docCnt)
            {
                cnt++;
                // Copy Desired Section from Mail Merge
                oWord.ActiveDocument.Sections[cnt].Range.Copy();
                // Set focus to the New Word Doc instance
                oNewWord.Activate();
                // Paste copied range to New Word Doc
                oNewWord.ActiveDocument.Range(0, 0).Paste();
                // Save New Word Doc
                oNewWord.ActiveDocument.SaveAs2(@"C:\Users\NAME\Desktop\SuccesfullySavedDoc-" + cnt + ".doc");

                // Clear New Word Doc 
                oNewWord.ActiveDocument.Content.Select();
                oNewWord.Selection.TypeBackspace();

                // Set Mail Merge as Active Document
                oWord.Activate();
            }

        // .............

        // Save new docuemnt...?
        oNewWrdDoc.SaveAs2("SuccesfullySavedTest.doc");

    }
    catch (Exception ex)
    {
        MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
    }
    finally
    {
        //
    }
}

...

EDIT3: документ очищается с каждой новой итерацией цикла. Теперь пытаюсь понять, почему каждый документ сохраняется с лишней пустой страницей 2.

Грубый план:

Документ 1: Запись 1 + дополнительная пустая страница (не знаете, почему?)

Документ 2: Запись 2 + дополнительная пустая страница (не знаете, почему?)

Документ 3: ЗАПИСЬ 3 + дополнительная пустая страница (не знаете, почему?)


person Analytic Lunatic    schedule 26.11.2013    source источник
comment
Кстати, если у вас есть полный контроль над содержимым/форматом документа, вы можете рассмотреть возможность использования материала Эрика Уайта для создания такого рода вывода — он вообще не использует MailMerge и гораздо больше соответствует способу .NET. делать вещи - ericwhite.com/blog/category/open-xml/ серия-генерация-документов   -  person    schedule 28.11.2013
comment
Лично я бы подумал о том, чтобы закрыть документ oNewWord после того, как вы сохранили его, создав новый внутри цикла, который у вас есть. Я сомневаюсь, что это будет главный хит производительности.   -  person    schedule 02.12.2013
comment
Это вариант, но я бы предпочел пойти по этому пути (если это возможно), просто чтобы сэкономить на небольшом кодировании и сделать вещи понятными для тех, кто может стать жертвой обслуживания/обновления через годы.   -  person Analytic Lunatic    schedule 02.12.2013
comment
@bibadia, понял! Теперь мне просто нужно выяснить, какие дополнительные пустые страницы добавляются к каждому документу во время Paste(). Я обновил свой код выше.   -  person Analytic Lunatic    schedule 02.12.2013
comment
Вы, возможно, вы получаете символ разрыва раздела в конце. Я бы попробовал проверить последний символ в каждом документе (может варьироваться в зависимости от того, является ли он последним разделом или предыдущим разделом) и удалить его. Но тогда вам нужно убедиться, что вы также не удаляете верхние/нижние колонтитулы.   -  person    schedule 03.12.2013


Ответы (1)


Несколько моментов:

Одна или две часто используемые бесплатные сторонние надстройки для сохранения в виде нескольких именованных документов имеют видимый код VBA, который вы могли бы перепроектировать/переписать на C#.

Раньше я использовал фрагмент кода, который выполнял одно слияние для каждой записи в источнике данных. Кто-то опубликовал одну версию моего старого кода в конце своего сообщения здесь.

Все эти методы могут не сработать по ряду причин. Сторонние методы иногда генерируют один вывод, а затем разбивают вывод при каждом разрыве раздела. Это будет работать только для некоторых типов слияния и в случае, если в основном документе слияния нет дополнительных разрывов разделов. «мой» код работает только в том случае, если слияние потребляет одну запись за раз (очевидно, его можно адаптировать для 2 записей на слияние и т. д., но если основной документ слияния содержит поля NEXT, NEXTIF или SKIPIF, тогда записи, потребляемые для слияния может варьироваться, и проблема заключается в том, что AFAIK невозможно определить, сколько записей было использовано (если только вы не можете положиться на размещение счетчика в основном документе слияния).

Что касается других моментов, я думаю, вам нужно изменить эту часть:

    Word.Application oWord = new Word.Application();
    Word.Document oWrdDoc = new Word.Document();

    // New Document Instance
    Word.Application oNewWord = new Word.Application();
    Word.Document oNewWrdDoc = new Word.Document();

потому что (если C# или что-то еще не делает что-то, о чем я не знаю) нет никакой гарантии, что новый объект Word.Document будет создан с помощью любого из экземпляров Word.Application, которые вы только что создали. Я думаю, вам нужно что-то большее, как

Word.Document oWrdDoc = oWord.Documents.Add(); // you may need to provide some parameters here in C#

Аналогично для oNewWrdDoc

Как только вы их создадите, я думаю, что rng.FormattedText либо исчезнет, ​​либо его будет немного легче решить.

person Community    schedule 27.11.2013
comment
Спасибо за ответ! Проблема не в том, чтобы заставить работать сам Mail Merge; У меня есть это. То, что я пытаюсь сделать, это обработать мое слияние, загрузить его на экран для просмотра пользователем (все письма в 1 документе) (работает!), Затем после просмотра и печати пользователя (при желании) продолжить обработку кода, где я буду сохранить каждую страницу документа Word для слияния как отдельный документ в определенном месте. Кроме того, экземпляры Word.App() работают должным образом. Строка oNewWrdDoc = oNewWord.Documents.Open(docSave) использует экземпляр oNewWrdDoc и загружает в него этот документ. - person Analytic Lunatic; 02.12.2013
comment
Хорошо, я видел ваши изменения и также вижу, что мое предложение о слиянии для каждой записи неактуально. Какая проблема возникает при использовании oNewWrdDoc.Range.FormattedText = oWord.ActiveDocument.Sections[1].Range.FormattedText; (В VBA здесь все работает нормально, но я думаю, что вы получите верхние/нижние колонтитулы только для раздела 1 — чтобы их также передать, если они у вас есть, вам, возможно, придется скопировать диапазоны из более чем одного диапазона) - person ; 02.12.2013
comment
Дайте мне минуту, чтобы вставить РЕДАКТИРОВАТЬ. Я добился большего прогресса. - person Analytic Lunatic; 02.12.2013
comment
См. РЕДАКТИРОВАТЬ. Теперь я пытаюсь очистить свой экземпляр Word Doc во время каждого цикла обработки следующих записей (раздел слияния). - person Analytic Lunatic; 02.12.2013