使用打印设置从WPF打印Word文档(生成的姿势) [英] Print Word document from WPF with print settings (Aspose generated)

查看:194
本文介绍了使用打印设置从WPF打印Word文档(生成的姿势)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在与印刷问题作斗争很长时间了,希望有人能提供帮助.

背景 我正在从一个单词模板创建一个Aspose.Words文档,并通过邮件合并它,然后希望使用打印对话框直接从WPF应用程序中打印它. 打印时,我需要能够选择适用于我的打印机的所有不同打印机设置(要使用的纸张,缩放,方向,颜色等).这最后一件事似乎是使我的Google搜索无法成功的原因,因为我发现的所有示例仅涉及给出打印机名称或要打印多少份.

测试1-Aspose的首选打印方式 从他们的论坛中

    private void Print(Document document)
    {
        var printDialog = new System.Windows.Forms.PrintDialog
        {
            AllowSomePages = true,
            PrinterSettings = new PrinterSettings
            {
                MinimumPage = 1,
                MaximumPage = document.PageCount,
                FromPage = 1,
                ToPage = document.PageCount
            },
            UseEXDialog = true
        };

        var result = printDialog.ShowDialog();
        if (result.Equals(DialogResult.OK))
            document.Print(printDialog.PrinterSettings);
    }

现在,这似乎是完美的!但是我遇到了两个问题.

  • 文本在页面上被加倍,因为它似乎首先使用默认字体打印,然后使用我的特殊字体打印第二,在第一字体的顶部.参见屏幕截图: 很抱歉,这是docx文件中的一个隐藏图像,以某种方式转换(即使隐藏在Word中)时,它也显示在最前面.

  • 速度太慢了……即使打印只有两页,也没有图形,但要花很多时间才能打印文档.

测试2-使用流程打印(PDF)

    private void Print(Document document)
    {
        var savePath = String.Format("C:\\temp\\a.pdf");
        document.Save(savePath, SaveFormat.Pdf);

        var myProcess = new Process();
        myProcess.StartInfo.FileName = savePath;
        myProcess.StartInfo.Verb = "Print";
        //myProcess.StartInfo.CreateNoWindow = true;
        myProcess.Start();
        myProcess.WaitForExit();
    }

这将是一个不错的解决方案,但它不会给我对话框(我可以使用单词PrintTo并提供一些参数,例如打印机名称等.但不是出于我的特殊要求,对吧?)

测试3-使用Word Automation打印

    private void Print(Document document)
    {
        object nullobj = Missing.Value;

        var savePath = String.Format("C:\\temp\\a.docx");
        document.Save(savePath, SaveFormat.Docx);

        var wordApp = new Microsoft.Office.Interop.Word.Application();
        wordApp.DisplayAlerts = Microsoft.Office.Interop.Word.WdAlertLevel.wdAlertsNone;
        wordApp.Visible = false;

        Microsoft.Office.Interop.Word.Document doc = null;
        Microsoft.Office.Interop.Word.Documents docs = null;
        Microsoft.Office.Interop.Word.Dialog dialog = null;
        try
        {
            docs = wordApp.Documents;
            doc = docs.Open(savePath);

            doc.Activate();
            dialog = wordApp.Dialogs[Microsoft.Office.Interop.Word.WdWordDialog.wdDialogFilePrint];
            var dialogResult = dialog.Show(ref nullobj);
            if (dialogResult == 1)
            {
                doc.PrintOut(false);
            }
        }catch(Exception)
        {
            throw;
        }finally
        {
            Thread.Sleep(3000);
            if (dialog != null) Marshal.FinalReleaseComObject(dialog);
            if (doc != null) Marshal.FinalReleaseComObject(doc);
            if (docs != null) Marshal.FinalReleaseComObject(docs);

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();

            doc = null;
            wordApp.Quit(false, ref nullobj, ref nullobj);
        }

    }

好吧,那我应该使用自动化吗?它可以正常打印,但是在关闭word-app和文档时遇到麻烦.例如,有时我会看到对话框可打印​​区域外的页边距",然后跳动,代码无法退出该过程并离开该过程. 您看到Thread.Sleep吗?如果我在那里没有,Word将在打印完成之前退出.

您知道,我在所有尝试中都达不到.最好的方法是什么?

感谢您的时间!

解决方案

好,我找到了合适的WPF解决方案,将文档转换为XPS并将其加载到DocumentViewer中,可以使用其本机打印功能. /p>

View.xaml

<DocumentViewer Document="{Binding XpsFixedDocumentSequence}"/>

ViewModel.cs

using System.Windows.Xps.Packaging;
...

private void PrepareDocument(Document document)
{
    var xpsDoc = GetDocumentAsXps(document);
    XpsFixedDocumentSequence = xpsDoc.GetFixedDocumentSequence();
}

private XpsDocument GetDocumentAsXps(Document document)
{
    var savePath = "C:\\temp\\doc.xps";
    document.Save(savePath, SaveFormat.Xps);
    var xpsDoc = new XpsDocument(savePath, FileAccess.Read);
    return xpsDoc;
}

/* Property XpsFixedDocumentSequence */
public const string XpsFixedDocumentSequencePropertyName = "XpsFixedDocumentSequence";
private FixedDocumentSequence _xpsFixedDocumentSequence;
public FixedDocumentSequence XpsFixedDocumentSequence
{
    get { return _xpsFixedDocumentSequence; }

    set
    {
        if (_xpsFixedDocumentSequence == value) return;
        _xpsFixedDocumentSequence = value;
        RaisePropertyChanged(XpsFixedDocumentSequencePropertyName);
    }
}

注意事项:引用ReachFramework dll

I've been fighting with a printing issue for a long time now, hopefully someone can help.

Background I'm creating an Aspose.Words-document from a word-template, and mail merging it, and then want to print it directly from the WPF application with a print dialog. When printing i need to be able to select all different printer settings available for my printer (what paper to use, zoom, orientation, color etc.). This last thing seems to be what keeps my Google searches from succeeding, as all examples I find is only about giving the printer name, or how many copies to print.

Test 1 - Aspose's preferred way of printing From their forum

    private void Print(Document document)
    {
        var printDialog = new System.Windows.Forms.PrintDialog
        {
            AllowSomePages = true,
            PrinterSettings = new PrinterSettings
            {
                MinimumPage = 1,
                MaximumPage = document.PageCount,
                FromPage = 1,
                ToPage = document.PageCount
            },
            UseEXDialog = true
        };

        var result = printDialog.ShowDialog();
        if (result.Equals(DialogResult.OK))
            document.Print(printDialog.PrinterSettings);
    }

Now this seems to be perfect! But I get two one issue(s).

  • The text is doubled on the page, as it seems to print with the default font first, and second with my special font second, on top of the first. See screencap: Sorry about this one, it was a hidden Image inside the docx-file, which came to the front when converted somehow (even though hidden in Word).

  • It is dog slow... it takes forever for document.Print, even though it's only 2 pages to print, and no graphics.

Test 2 - Print with process (PDF)

    private void Print(Document document)
    {
        var savePath = String.Format("C:\\temp\\a.pdf");
        document.Save(savePath, SaveFormat.Pdf);

        var myProcess = new Process();
        myProcess.StartInfo.FileName = savePath;
        myProcess.StartInfo.Verb = "Print";
        //myProcess.StartInfo.CreateNoWindow = true;
        myProcess.Start();
        myProcess.WaitForExit();
    }

This would be a nice solution, but it doesn't give me the dialog (I can use word PrintTo and give some arguments, like printer name etc. But not for my special requirements, right?)

Test 3 - Print with Word Automation

    private void Print(Document document)
    {
        object nullobj = Missing.Value;

        var savePath = String.Format("C:\\temp\\a.docx");
        document.Save(savePath, SaveFormat.Docx);

        var wordApp = new Microsoft.Office.Interop.Word.Application();
        wordApp.DisplayAlerts = Microsoft.Office.Interop.Word.WdAlertLevel.wdAlertsNone;
        wordApp.Visible = false;

        Microsoft.Office.Interop.Word.Document doc = null;
        Microsoft.Office.Interop.Word.Documents docs = null;
        Microsoft.Office.Interop.Word.Dialog dialog = null;
        try
        {
            docs = wordApp.Documents;
            doc = docs.Open(savePath);

            doc.Activate();
            dialog = wordApp.Dialogs[Microsoft.Office.Interop.Word.WdWordDialog.wdDialogFilePrint];
            var dialogResult = dialog.Show(ref nullobj);
            if (dialogResult == 1)
            {
                doc.PrintOut(false);
            }
        }catch(Exception)
        {
            throw;
        }finally
        {
            Thread.Sleep(3000);
            if (dialog != null) Marshal.FinalReleaseComObject(dialog);
            if (doc != null) Marshal.FinalReleaseComObject(doc);
            if (docs != null) Marshal.FinalReleaseComObject(docs);

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();

            doc = null;
            wordApp.Quit(false, ref nullobj, ref nullobj);
        }

    }

Ok, so should I use Automation? It prints fine, but when it comes to closing the word-app and document I get trouble. For example I sometimes get the dialog "Margins outside printable area", and woops, the code cannot quit the process and leaves it. You see the Thread.Sleep? If I dont have it there, Word will be quitted before the printing has finished.

You see, I fall short in all my tries. What is the best way to go about this?

Thanks for your time!

解决方案

OK, I found a proper WPF-solution, converting the document to XPS and loading it into a DocumentViewer, from which I can use the native print functionality.

View.xaml

<DocumentViewer Document="{Binding XpsFixedDocumentSequence}"/>

ViewModel.cs

using System.Windows.Xps.Packaging;
...

private void PrepareDocument(Document document)
{
    var xpsDoc = GetDocumentAsXps(document);
    XpsFixedDocumentSequence = xpsDoc.GetFixedDocumentSequence();
}

private XpsDocument GetDocumentAsXps(Document document)
{
    var savePath = "C:\\temp\\doc.xps";
    document.Save(savePath, SaveFormat.Xps);
    var xpsDoc = new XpsDocument(savePath, FileAccess.Read);
    return xpsDoc;
}

/* Property XpsFixedDocumentSequence */
public const string XpsFixedDocumentSequencePropertyName = "XpsFixedDocumentSequence";
private FixedDocumentSequence _xpsFixedDocumentSequence;
public FixedDocumentSequence XpsFixedDocumentSequence
{
    get { return _xpsFixedDocumentSequence; }

    set
    {
        if (_xpsFixedDocumentSequence == value) return;
        _xpsFixedDocumentSequence = value;
        RaisePropertyChanged(XpsFixedDocumentSequencePropertyName);
    }
}

Note to self: reference the ReachFramework dll

这篇关于使用打印设置从WPF打印Word文档(生成的姿势)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆