Show / Hide Table of Contents

MSDN.WhiteKnight - Stack Overflow answers

Ответ на "Как определить формат файла excel?"

Answer 1005851

Link

Как вариант, в Windows для определения, является ли файл корректным XLS-файлом, можно использовать Structured Storage API. Согласно спецификации, формат XLS - это файл формата Structured Storage, который содержит поток с именем Workbook.

MS-XLS: Excel Binary File Format Structure, пункт 2.1.2:

A file of the type specified by this document consists of storages and streams as specified in [MS-CFB]...

A workbook MUST contain the workbook stream...

Можно использовать следующий код для проверки на XLS, на основе этого правила:

using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("ole32.dll")]
        static extern int StgOpenStorageEx(
            [MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
            uint grfMode,
            uint stgfmt,
            uint grfAttrs,
            IntPtr pStgOptions,
            IntPtr reserved2,
            [In] ref Guid riid,
            out IStorage ppObjectOpen);

        const uint STGM_DIRECT = 0;
        const uint STGM_READ = 0;        
        const uint STGM_SHARE_EXCLUSIVE = 0x10;        
        const uint STGFMT_STORAGE = 0;        
        const uint PID_FIRST_USABLE = 2;
        const uint STGC_DEFAULT = 0;               

        [Guid("0000000B-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IStorage
        {
            void a();
            
            [PreserveSig]
            int OpenStream(string pwcsName, 
                IntPtr reserved1, 
                uint grfMode, 
                uint reserved2, 
                [MarshalAs(UnmanagedType.Interface)] out object ppstm);
            
            void CreateStorage(string pwcsName, uint grfMode,  uint reserved1, uint reserved2, out IStorage ppstg);            
            void OpenStorage(string pwcsName, IStorage pstgPriority,  uint grfMode,  IntPtr snbExclude, uint reserved, out IStorage ppstg);            
            void CopyTo( uint ciidExclude, Guid[] rgiidExclude,  IntPtr snbExclude, IStorage pstgDest);            
            void MoveElementTo(string pwcsName, IStorage pstgDest, string pwcsNewName, uint grfFlags);            
            void Commit( uint grfCommitFlags);            
            void Revert();            
            void b();            
            void DestroyElement(string pwcsName);            
            void RenameElement(string pwcsOldName, string pwcsNewName);            
            void c();            
            void SetClass( ref Guid clsid);            
            void SetStateBits( uint grfStateBits,  uint grfMask);            
            void d();
        }

        public static bool IsXLS(string path)
        {            
            IStorage pStorage = null;
            object o = null;
            int hr;            
            Guid guidStorage = typeof(IStorage).GUID;            

            try
            {
                //открываем файл
                hr = StgOpenStorageEx(path, STGM_READ | STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE,
                    0, IntPtr.Zero, IntPtr.Zero, ref guidStorage, out pStorage);

                if (hr != 0) return false; //NOT Structured storage file                 
                       
                //открываем поток
                hr = pStorage.OpenStream("Workbook", IntPtr.Zero, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, out o);
                                            
                return hr == 0;
            }
            finally
            {
                //освобождение ресурсов                
                if (pStorage != null) Marshal.ReleaseComObject(pStorage);
                if (o != null) Marshal.ReleaseComObject(o);
            }
        }       
    }  
}

Так как файл XLSX является ZIP-архивом определенной структуры, можно применить для проверки ту же логику, и воспользоваться любой библиотекой для работы с ZIP-архивами (в .NET 4.5+ есть встроенная System.IO.Compression).


Content is retrieved from StackExchange API.

Auto-generated by ruso-archive tools.

Back to top Stack Overflow answers (published from sources in GitHub repository). Copyright (c) 2020, MSDN.WhiteKnight. Content licensed under BSD 3-Clause License.
Generated by DocFX