6

我使用我的 c# 应用程序创建了一些 excel 文件并将它们保存在我的电脑中。我想在我的应用程序中打开并查看它们我该怎么做?我的应用程序是使用 WPF C# 开发的

4

3 回答 3

6

您可以利用预览处理程序机制。这是我为托管预览处理程序所做的控件:

public class FilePreviewControl : HwndHost {
    private const int
        Child = 0x40000000,
        Visible = 0x10000000,
        HostId = 0x00000002,
        ClipChild = 0x02000000;

    public static readonly DependencyProperty PathProperty = DependencyProperty.Register(
        "Path", typeof (string), typeof (FilePreviewControl), new UIPropertyMetadata(Update));

    public static readonly DependencyProperty ExtensionProperty = DependencyProperty.Register(
        "Extension", typeof (string), typeof (FilePreviewControl), new UIPropertyMetadata(Update));

    public static readonly DependencyProperty SourceStreamProperty = DependencyProperty.Register(
        "SourceStream", typeof (Stream), typeof (FilePreviewControl), new UIPropertyMetadata(Update));

    private readonly PreviewManager manager;
    private IntPtr hwndHost;

    public FilePreviewControl() {
        this.manager = new PreviewManager();
    }

    public Stream SourceStream {
        get { return (Stream) this.GetValue(SourceStreamProperty); }
        set { this.SetValue(SourceStreamProperty, value); }
    }

    public string Extension {
        get { return (string) this.GetValue(ExtensionProperty); }
        set { this.SetValue(ExtensionProperty, value); }
    }

    public string Path {
        get { return (string) this.GetValue(PathProperty); }
        set { this.SetValue(PathProperty, value); }
    }

    private static void Update(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        ((FilePreviewControl) d).RefreshPreview();
    }

    protected override HandleRef BuildWindowCore(HandleRef hwndParent) {
        this.hwndHost = IntPtr.Zero;

        this.hwndHost = CreateWindowEx(0, "static", "",
            Child | Visible | ClipChild,
            0, 0,
            (int) this.ActualWidth, (int) this.ActualHeight,
            hwndParent.Handle,
            (IntPtr) HostId,
            IntPtr.Zero,
            0);

        this.RefreshPreview();

        return new HandleRef(this, this.hwndHost);
    }

    protected override void DestroyWindowCore(HandleRef hwnd) {
        DestroyWindow(hwnd.Handle);
        this.manager.Dispose();
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) {
        base.OnRenderSizeChanged(sizeInfo);
        var rect = new Rect(new Size(this.ActualWidth, this.ActualHeight));
        this.manager.InvalidateAttachedPreview(rect);
    }

    protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
        handled = false;
        return IntPtr.Zero;
    }

    [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
    private static extern IntPtr CreateWindowEx(
        int dwExStyle,
        string lpszClassName,
        string lpszWindowName,
        int style,
        int x,
        int y,
        int width,
        int height,
        IntPtr hwndParent,
        IntPtr hMenu,
        IntPtr hInst,
        [MarshalAs(UnmanagedType.AsAny)] object pvParam);

    [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
    private static extern bool DestroyWindow(IntPtr hwnd);

    private void RefreshPreview() {
        if (this.hwndHost == IntPtr.Zero)
            return;

        var filePath = this.Path;
        var extension = this.Extension;

        if (string.IsNullOrEmpty(extension) && !string.IsNullOrEmpty(filePath))
            extension = System.IO.Path.GetExtension(filePath);

        var shouldBeDeactivated =
            this.Visibility != Visibility.Visible ||
            (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) && this.SourceStream == null ||
            string.IsNullOrEmpty(extension);

        if (shouldBeDeactivated) {
            this.manager.Detach();
            return;
        }

        var rect = new Rect(new Size(this.RenderSize.Width, this.RenderSize.Height));

        try {
            this.manager.AttachPreview(
                this.hwndHost,
                rect,
                extension,
                filePath,
                this.SourceStream);
        } catch (Exception exception) {
            Trace.TraceError(exception.ToString());
        }
    }

    public static bool CanPreview(string extension) {
        return PreviewManager.GetPreviewHandlerKey(extension) != null;
    }

    #region Nested type: InteropStream

    private sealed class InteropStream : IStream, IDisposable {
        private readonly Stream stream;
        private bool disposed;

        public InteropStream(Stream sourceStream) {
            if (sourceStream == null)
                throw new ArgumentNullException("sourceStream");

            this.stream = sourceStream;
        }

        #region IDisposable Members

        public void Dispose() {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

        #region IStream Members

        public void Clone(out IStream ppstm) {
            throw new NotSupportedException();
        }

        public void Commit(int grfCommitFlags) {
            throw new NotSupportedException();
        }

        public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) {
            throw new NotSupportedException();
        }

        public void LockRegion(long libOffset, long cb, int dwLockType) {
            throw new NotSupportedException();
        }

        [SecurityCritical]
        public void Read(byte[] pv, int cb, IntPtr pcbRead) {
            var count = this.stream.Read(pv, 0, cb);
            if (pcbRead != IntPtr.Zero)
                Marshal.WriteInt32(pcbRead, count);
        }

        public void Revert() {
            throw new NotSupportedException();
        }

        [SecurityCritical]
        public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) {
            var origin = (SeekOrigin) dwOrigin;
            var pos = this.stream.Seek(dlibMove, origin);

            if (plibNewPosition != IntPtr.Zero)
                Marshal.WriteInt64(plibNewPosition, pos);
        }

        public void SetSize(long libNewSize) {
            this.stream.SetLength(libNewSize);
        }

        public void Stat(out STATSTG pstatstg, int grfStatFlag) {
            pstatstg = new STATSTG {
                type = 2,
                cbSize = this.stream.Length,
                grfMode = 0
            };

            if (this.stream.CanRead && this.stream.CanWrite)
                pstatstg.grfMode |= 2;

            else if (this.stream.CanWrite && !this.stream.CanRead)
                pstatstg.grfMode |= 1;

            else
                throw new IOException();
        }

        public void UnlockRegion(long libOffset, long cb, int dwLockType) {
            throw new NotSupportedException();
        }

        [SecurityCritical]
        public void Write(byte[] pv, int cb, IntPtr pcbWritten) {
            this.stream.Write(pv, 0, cb);

            if (pcbWritten != IntPtr.Zero)
                Marshal.WriteInt32(pcbWritten, cb);
        }

        #endregion

        private void Dispose(bool disposing) {
            if (this.disposed)
                return;

            if (disposing && this.stream != null)
                this.stream.Dispose();

            this.disposed = true;
        }

        ~InteropStream() {
            this.Dispose(false);
        }
    }

    #endregion

    private sealed class TempFile : IDisposable {
        private string path;

        public TempFile() : this(System.IO.Path.GetTempFileName()) {
        }

        private TempFile(string path) {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");
            this.path = path;
        }

        public string Path {
            get {
                if (this.path == null)
                    throw new ObjectDisposedException(this.GetType().Name);
                return this.path;
            }
        }

        #region IDisposable Members

        public void Dispose() {
            this.Dispose(true);
        }

        #endregion

        private void Dispose(bool disposing) {
            if (disposing)
                GC.SuppressFinalize(this);
            if (this.path == null)
                return;

            try {
                File.Delete(this.path);
            } catch {
                Trace.TraceWarning("Can't delete file " + this.path);
            } // best effort
            this.path = null;
        }

        ~TempFile() {
            this.Dispose(false);
        }
    }

    #region Nested type: PreviewManager

    private sealed class PreviewManager : IDisposable {
        private IPreviewHandler currentHandler;
        private bool disposed;
        private InteropStream stream;

        #region IDisposable Members

        public void Dispose() {
            this.DisposeInternal();
            GC.SuppressFinalize(this);
        }

        #endregion

        public void AttachPreview(IntPtr handler, Rect viewRect, string extension, string filePath,
            Stream sourceStream) {
            this.Unload();

            var classKey = GetPreviewHandlerKey(extension);

            if (classKey == null)
                return;

            var guid = new Guid(classKey.GetValue(string.Empty).ToString());

            var type = Type.GetTypeFromCLSID(guid, true);
            var instance = Activator.CreateInstance(type);

            var fileInit = instance as IInitializeWithFile;
            var streamInit = instance as IInitializeWithStream;

            if (streamInit != null && sourceStream != null) {
                this.stream = new InteropStream(sourceStream);
                streamInit.Initialize(this.stream, 0);
            } else if (fileInit != null)
                if (filePath != null)
                    fileInit.Initialize(filePath, 0);

                else if (sourceStream != null)
                    using (var tempFile = new TempFile()) {
                        using (var fileStream = File.Create(tempFile.Path))
                            sourceStream.CopyTo(fileStream);

                        fileInit.Initialize(tempFile.Path, 0);
                    }
                else
                    return;
            else
                return;

            this.currentHandler = instance as IPreviewHandler;

            if (this.currentHandler == null) {
                this.Unload();
                return;
            }

            var rect = new ShellRect(viewRect);

            this.currentHandler.SetWindow(handler, ref rect);
            this.currentHandler.SetRect(ref rect);

            try {
                this.currentHandler.DoPreview();
            } catch {
                this.Unload();
                throw;
            }
        }

        internal static RegistryKey GetPreviewHandlerKey(string extension) {
            var commonGuid = new Guid("8895b1c6-b41f-4c1c-a562-0d564250836f");

            var classKey =
                Registry.ClassesRoot.OpenSubKey(string.Format(@"{0}\ShellEx\{1:B}", extension, commonGuid));
            return classKey;
        }

        public void Detach() {
            this.Unload();
        }

        public void InvalidateAttachedPreview(Rect viewRect) {
            if (this.currentHandler == null)
                return;

            var rect = new ShellRect(viewRect);
            this.currentHandler.SetRect(ref rect);
        }

        private void DisposeInternal() {
            if (this.disposed)
                return;

            this.Unload();

            this.disposed = true;
        }

        private void Unload() {
            if (this.currentHandler != null) {
                this.currentHandler.Unload();
                Marshal.FinalReleaseComObject(this.currentHandler);
                this.currentHandler = null;
            }

            if (this.stream != null) {
                this.stream.Dispose();
                this.stream = null;
            }
        }

        ~PreviewManager() {
            this.DisposeInternal();
        }

        #region Nested type: IInitializeWithFile

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("b7d14566-0509-4cce-a71f-0a554233bd9b")]
        internal interface IInitializeWithFile {
            void Initialize([MarshalAs(UnmanagedType.LPWStr)] string pszFilePath, uint grfMode);
        }

        #endregion

        #region Nested type: IInitializeWithStream

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
        internal interface IInitializeWithStream {
            void Initialize(IStream pstream, uint grfMode);
        }

        #endregion

        #region Nested type: IPreviewHandler

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
        internal interface IPreviewHandler {
            void SetWindow(IntPtr hwnd, ref ShellRect rect);
            void SetRect(ref ShellRect rect);
            void DoPreview();
            void Unload();
            void SetFocus();
            void QueryFocus(out IntPtr phwnd);

            [PreserveSig]
            uint TranslateAccelerator(ref MSG pmsg);
        }

        #endregion

        #region Nested type: ShellRect

        [StructLayout(LayoutKind.Sequential)]
        internal struct ShellRect {
            public readonly int left;
            public readonly int top;
            public readonly int right;
            public readonly int bottom;

            public ShellRect(Rect rect) {
                this.top = (int) rect.Top;
                this.bottom = (int) rect.Bottom;
                this.left = (int) rect.Left;
                this.right = (int) rect.Right;
            }
        }

        #endregion
    }

    #endregion
}

以下是如何使用它:

<local:FilePreviewControl Path="Book1.xlsx" />

只有在您的计算机上安装了 Microsoft Office 时,它​​才会起作用。

于 2013-04-08T02:57:28.427 回答
6

您可以使用DocumentViewerWPF 控件。

首先,您应该将您的转换office documentXPS格式。请看这个帖子

然后将其绑定到控件的Document属性上。DocumentViewer

XAML

<DocumentViewer Name="myDocumentViewer" Margin="0,0,0,59">

</DocumentViewer>

代码背后

myDocumentViewer.Document = this.ConvertPptxDocToXPSDoc(this.FileName, this.newXPSDocumentName).GetFixedDocumentSequence();
于 2013-04-08T04:17:32.213 回答
3

上海证券交易所的解决方案被低估了。它工作得很好,优点是:

  • 没有 webBrowser 解决方案中的 activeX msgBox(打开、保存、取消)
  • 无需 regsvr32 dsoframer.ocx 在客户端机器中使用 AxFramerControl 解决方案作为管理员
  • 无需转换成XPS格式,保持Excel风格

缺点是:

  • 办公室是必需的
  • 当应用程序在 Windows 7 上关闭时,必须找到一种方法来终止 Excel 进程(在 Windows 10 上不需要,Excel 会自行终止)
  • 该文档是只读的

您只需添加:

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Security.AccessControl;

并添加最新的 Microsoft.Office.Interop.Excel 参考

我只想添加评论,但我没有足够的声誉。但是,此解决方案可以节省您的时间!

于 2019-03-13T10:49:05.363 回答