【问题标题】:Copy a visio page to a new document将 visio 页面复制到新文档
【发布时间】:2017-03-10 11:06:50
【问题描述】:

我想要完成的事情:
我想将我的 Visio 应用程序中的活动页面复制到一个新文档并保存(并将其设置为数据库的 byte[]),我已经这样做了,但方式有点“错误”,因为交互太多使用 Visio 应用程序。

将页面复制到字节数组的方法:

private static byte[] VisioPageToBytes()
{
    //Make a new invisible app to dump the shapes in
    var app = new InvisibleApp();

    Page page = MainForm.IVisioApplication.ActivePage;
    app.AlertResponse = 2;

    //Selact all shapes and copy, then deselect
    MainForm.IVisioApplication.ActiveWindow.SelectAll();
    MainForm.IVisioApplication.ActiveWindow.Selection.Copy();
    MainForm.IVisioApplication.ActiveWindow.DeselectAll();

    //Add empty document to invisible app and dump shapes
    app.Documents.Add( string.Empty );
    app.ActivePage.Paste();

    //Save document and convert to byte[]
    app.ActiveDocument.SaveAs( Application.UserAppDataPath + @"/LastStored.vsd" );
    app.ActiveDocument.Close();
    app.Quit();
    app.AlertResponse = 0;
    var bytes = File.ReadAllBytes( Application.UserAppDataPath + @"/LastStored.vsd" );
    Clipboard.Clear();
    return bytes;
}

为什么会出错:
此代码在 visio 页面中进行选择,并且必须打开一个不可见的窗口来存储页面。我正在寻找一种与 Visio 应用程序交互较少的方法(因为它不稳定)。打开第二个(不可见的)Visio 应用程序有时会使我的主 Visio 应用程序崩溃。

我想做类似的事情:

Page page = MainForm.IVisioApplication.ActivePage;
Document doc;
doc.Pages.Add( page ); //Pages.Add has no parameters so this doesn't work
doc.SaveAs(Application.UserAppDataPath + @"/LastStored.vsd");

如果以较少交互的方式(通过“构建”文档)无法做到这一点,请发表评论让我知道。

TL;DR;
我不想在不打开 Visio 的情况下制作新的 Visio 文档并将 1 页(的内容)复制到其中。

【问题讨论】:

  • 您是在表单还是独立应用程序中使用 Visio 绘图控件?如果是前者,那么控件一次只允许打开一个文档。另外,您是否有理由不想只保存为然后删除其他页面?
  • 不是绘图控件,是应用程序。如果你看代码你可以看到我做了一个不可见的应用程序,这不能用绘图控件来完成
  • @JohnGoldsmith 我正在处理(存储)每个页面上的数据,之后我们想在数据库中保留该页面的副本,因此我将其存储并保存到数据库中作为字节数组。如果我可以复制文档并删除页面而不在 visio 应用程序帖子中打开它们作为答案请:)

标签: c# office-interop visio


【解决方案1】:

如果您想创建一个复制页面,那么您可能会发现 Page 上的 Duplicate 方法很方便,但听上去只需保存现有文档即可:

void Main()
{
    var vApp = MyExtensions.GetRunningVisio();

    var sourcePage = vApp.ActivePage;
    var sourcePageNameU = sourcePage.NameU;
    var vDoc = sourcePage.Document;
    vDoc.Save(); //to retain original
    var origFileName = vDoc.FullName;

    var newFileName = Path.Combine(vDoc.Path, $"LastStored{Path.GetExtension(origFileName)}");
    vDoc.SaveAs(newFileName);

    //Remove all other pages
    for (short i = vDoc.Pages.Count; i > 0; i--)
    {
        if (vDoc.Pages[i].NameU != sourcePageNameU)
        {
            vDoc.Pages[i].Delete(0);
        }
    }

    //Save single page state
    vDoc.Save();

    //Close copy and reopen original
    vDoc.Close();
    vDoc = vApp.Documents.Open(origFileName);
}

GetRunningVisio 是我与 LinqPad 一起使用的扩展方法:

http://visualsignals.typepad.co.uk/vislog/2015/12/getting-started-with-c-in-linqpad-with-visio.html

...但是您已经获得了对您的应用的引用,因此您可以使用它。

基于 cmets 的更新:

好的,那么对您的原始代码进行修改怎么样?请注意,我正在从页面创建一个新的 Selection 对象,但没有更改 Window 对象,因此这不应该影响用户看到的内容或更改源文档。

void Main()
{
    var vApp = MyExtensions.GetRunningVisio();

    var sourcePage = vApp.ActivePage;
    var sourceDoc = sourcePage.Document;
    var vSel = sourcePage.CreateSelection(Visio.VisSelectionTypes.visSelTypeAll);
    vSel.Copy(Visio.VisCutCopyPasteCodes.visCopyPasteNoTranslate);

    var copyDoc = vApp.Documents.AddEx(string.Empty,
                         Visio.VisMeasurementSystem.visMSDefault,
                         (int)Visio.VisOpenSaveArgs.visAddHidden);
    copyDoc.Pages[1].Paste(Visio.VisCutCopyPasteCodes.visCopyPasteNoTranslate);

    var origFileName = sourceDoc.FullName;
    var newFileName = Path.Combine(sourceDoc.Path, $"LastStored{Path.GetExtension(origFileName)}");
    copyDoc.SaveAs(newFileName);
    copyDoc.Close();
}

请注意,这只会创建一个默认页面,因此您可能希望在粘贴之前包括复制页面单元格,例如 PageWidth、PageHeight、PageScale 和 DrawingScale 等。

【讨论】:

  • 现有文档有40页,我只想保存1页:)
  • 页面上的复制方法复制当前文档中仍在执行工作的页面。我希望它与当前文档/应用程序分开
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 2020-03-07
  • 1970-01-01
  • 2019-11-25
  • 2023-03-21
  • 2018-06-23
  • 1970-01-01
相关资源
最近更新 更多