none
Excel2007で、ブックの保護を行ったxlsxをVBAで開こうとするとエラーが発生する RRS feed

  • 質問

  • Excel2010をインストールしたマシンで、
    タイプライブラリを利用して、暗号化がかかっているxlsファイルを
    チェックするモジュールを作っています。

    下記のようなコードを使用し、暗号化され、パスワード問い合わせのダイアログが表示されるファイルであれば、
    Openでエラーを発生させて、処理から弾いています。

    ですが、Excel2007でブックの保護のみを行ったxlsxファイルを処理すると、
    Workbooks.Openの際に、暗号化されたファイル同様、
     「入力したパスワードが間違っています。CapsLockキーの状態に注意して、大文字と小文字が正しく使われていることを確認してください。」
    とエラーが発生します。
    エラーになるファイルは、Excel上で開いてもパスワード問い合わせはされず、
    また、同様の操作であっても、Excel2010で作成したxlsxファイルであれば、エラーになりません。

    暗号化されたものと、ブック保護されたものを判別する方法はないでしょうか。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Office.Interop.Excel;
    using System.Windows.Forms;
    using System.IO;

    static public bool CheckExcel(string strPrintFile)
    {
        Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel._Workbook objExcelXls = null;
        Microsoft.Office.Interop.Excel.Workbooks objBooks = oXL.Workbooks;
        Microsoft.Office.Interop.Excel._Worksheet objSheetXls;
        Microsoft.Office.Interop.Excel._Chart objChartXls;

        try
        {
            oXL.AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable;

            objExcelXls = oXL.Workbooks.Open(
                strPrintFile,
                0, Type.Missing, Type.Missing, "password", "password", true,
                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

        catch (Exception ex)
        {
            string strErrMsg = ex.Message;
            return false;
        }
        finally
        {
            if (objExcelXls != null)
            {
                objExcelXls.Close(false, Type.Missing, Type.Missing);
            }
            objExcelXls = null;
            oXL.Quit();
            oXL = null;
        }

    2011年1月31日 5:39

回答

  • Excel 2007とExcel 2010で

    1. 何もしない
    2. パスワード無しでブックを保護
    3. パスワード有りでブックを保護
    4. 暗号化(パスワードは必ず必要)

    を実行したファイルをメモ帳で開いてみたところ、

    1. どちらも暗号化なし
    2. どちらも暗号化なし
    3. Excel 2007は暗号化される。Excel 2010は暗号化なし
    4. どちらも暗号化される

    という結果でした。

    そして、ファイルの中身が暗号化されている場合

    1. Password引数に文字列(空であっても)を指定 → 一致しなければエラー
    2. Password引数を省略 or Type.Missingを指定 → 上記3の場合には開ける、上記4の場合にはパスワード入力ダイアログ表示

    となってました。

    したがって、Passwordに文字列を入れてしまうと判別不能になるので、

    Password指定せずにパスワード入力ダイアログの有無で判断するしかないような気がします。

    たとえば、こんな感じで。(Excelのプロセスが大量に残る恐れあり)

      class OfficePasswordChecker
      {
        private Excel.Application _app;
        private int _waitTimeAfterCallOpenMethod = 1000;
        private int _waitTimeAfterSendEnterKey = 1000;
    
        public OfficePasswordChecker(string path)
        {
          _app = new Excel.Application();
    
          (
            new Thread(
              new ThreadStart(
                delegate
                {
                  try
                  {
                    _app.Workbooks.Open(Filename: path);
                  }
                  catch { } // パスワード入力後に例外が発生するのでとりあえず握りつぶしておく
                  }
              )
            )
          ).Start();
    
          Thread.Sleep(_waitTimeAfterCallOpenMethod);
    
          // パスワード入力の要不要にかかわらずここまでくるため、
           // この時点での判断は無理
        }
    
        public bool GetResult()
        {
          try
          {
            _app.Quit();
    
            // パスワード入力ダイアログが開かれている場合はQuitでエラーが発生
              // ->エラーがあった場合には、パスワードが必要であったと仮定する
              //  ※実際には他の影響によりエラーが出る場合もありうるが、それは無視する
    
              return true;
          }
          catch
          {
            // このまま終了するとExcelが起動したままになるため、
              // パスワード入力ダイアログに、パスワード入力無しでOKを押す操作を行う
    
              SendKeys.SendWait("{ENTER}");
            Thread.Sleep(_waitTimeAfterSendEnterKey);
            _app.Quit();
            return false;
          }
        }
      }
    
    • 回答としてマーク sviurr 2011年2月9日 4:23
    2011年2月5日 4:47

すべての返信

  • Excel 2007とExcel 2010で

    1. 何もしない
    2. パスワード無しでブックを保護
    3. パスワード有りでブックを保護
    4. 暗号化(パスワードは必ず必要)

    を実行したファイルをメモ帳で開いてみたところ、

    1. どちらも暗号化なし
    2. どちらも暗号化なし
    3. Excel 2007は暗号化される。Excel 2010は暗号化なし
    4. どちらも暗号化される

    という結果でした。

    そして、ファイルの中身が暗号化されている場合

    1. Password引数に文字列(空であっても)を指定 → 一致しなければエラー
    2. Password引数を省略 or Type.Missingを指定 → 上記3の場合には開ける、上記4の場合にはパスワード入力ダイアログ表示

    となってました。

    したがって、Passwordに文字列を入れてしまうと判別不能になるので、

    Password指定せずにパスワード入力ダイアログの有無で判断するしかないような気がします。

    たとえば、こんな感じで。(Excelのプロセスが大量に残る恐れあり)

      class OfficePasswordChecker
      {
        private Excel.Application _app;
        private int _waitTimeAfterCallOpenMethod = 1000;
        private int _waitTimeAfterSendEnterKey = 1000;
    
        public OfficePasswordChecker(string path)
        {
          _app = new Excel.Application();
    
          (
            new Thread(
              new ThreadStart(
                delegate
                {
                  try
                  {
                    _app.Workbooks.Open(Filename: path);
                  }
                  catch { } // パスワード入力後に例外が発生するのでとりあえず握りつぶしておく
                  }
              )
            )
          ).Start();
    
          Thread.Sleep(_waitTimeAfterCallOpenMethod);
    
          // パスワード入力の要不要にかかわらずここまでくるため、
           // この時点での判断は無理
        }
    
        public bool GetResult()
        {
          try
          {
            _app.Quit();
    
            // パスワード入力ダイアログが開かれている場合はQuitでエラーが発生
              // ->エラーがあった場合には、パスワードが必要であったと仮定する
              //  ※実際には他の影響によりエラーが出る場合もありうるが、それは無視する
    
              return true;
          }
          catch
          {
            // このまま終了するとExcelが起動したままになるため、
              // パスワード入力ダイアログに、パスワード入力無しでOKを押す操作を行う
    
              SendKeys.SendWait("{ENTER}");
            Thread.Sleep(_waitTimeAfterSendEnterKey);
            _app.Quit();
            return false;
          }
        }
      }
    
    • 回答としてマーク sviurr 2011年2月9日 4:23
    2011年2月5日 4:47

  • コード上で判断して、解決するのは難しそうですね・・・。
    2007だと、Excel上では開けても、内容としては暗号化されてしまっているのですか。

    コードまで頂き、有りがたいです。
    自動化処理の中でEXCELのチェックをしようと考えています。
    他のアプリも稼働しているため、実際にダイアログを出した上で判定は避けたいと思っています。
    プロセスが残ってしまうことも避けたいです。

    2007のxlsxのみで、業務的にブック保護はレアケースなので、
    運用的に制限する方向で考えてみます。

    回答ありがとうございました。

    2011年2月9日 4:23