その他

VBA「書き込みできません。」のエラー解消&再発防止方法[No79]

投稿日:2020年10月28日 更新日:

スポンサーリンク

今回の投稿はSeleniumBasic(セレニウムベーシック)を例に紹介しますが、これ以外でも有効な情報と思います。

イントロ

エラー内容

  • Microsoft Visual Basic
  • 実行時エラー '70'
  • 書き込みできません。

エラー画像

イントロ

このエラーはファイルが既に使われている(使用中・開かれている)時に表示されます。

今回はVBAでSeleniumBasicを実行し、1回目の処理では発生しないが何故か2回処理を実行させると同エラーが表示されました。

そして調べてもそのファイルは閉じているものと思っていました。

プログラム

紹介するプログラムは以下記事のように、Webドライバーの実行ファイル(exeファイル)をローカルにコピーして使う場合のものです。

no image
selenium BasicのWebDriverバージョン管理について[No61]
seleniumBasicを用いるプログラムの保守性を高めるポイントに「WebDriverのバージョンを管理する」があると思います。 Edge、chrome、ie、firefoxなど ...

エラーになる場合


Option Explicit

Dim testDriver As New Selenium.WebDriver

Public Sub sample_test01()
    'ChromeDriver | EdgeDriver | IEDriver | OperaDriver
    'FirefoxDriver | PhantomJSDriver
    'Dim testDriver As New Selenium.WebDriver
    Set testDriver = New Selenium.WebDriver
    
    Dim driverTargetPath:
    Dim driverOriginPath:
    
    'chrome(WebDriverまたはChromeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Chrome\86_0_4_40_22\chromedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\chromedriver.exe"

    'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Microsoft_Edge\85_0_564_63\msedgedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\edgedriver.exe"
    
    'Debug.Print Now & "driverTargetPath:" & driverTargetPath
    'Debug.Print Now & "driverOriginPath:" & driverOriginPath
    FileCopy driverTargetPath, driverOriginPath
    
    With testDriver
        'chrome(WebDriverまたはChromeDriver)の場合
        '.Start "chrome"
        
        'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
        .Start "MicrosoftEdge"

        .Get "http://www.yahoo.co.jp/"
        '.Quit
        .Close
    End With
End Sub

FileCopyのコピーのところでエラーになります。

エラーにならない場合


Option Explicit

'Dim testDriver As New Selenium.WebDriver

Public Sub sample_test02()
    'ChromeDriver | EdgeDriver | IEDriver | OperaDriver
    'FirefoxDriver | PhantomJSDriver
    Dim testDriver As New Selenium.WebDriver
    Set testDriver = New Selenium.WebDriver
    
    Dim driverTargetPath:
    Dim driverOriginPath:
    
    'chrome(WebDriverまたはChromeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Chrome\86_0_4_40_22\chromedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\chromedriver.exe"

    'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Microsoft_Edge\85_0_564_63\msedgedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\edgedriver.exe"
    
    'Debug.Print Now & "driverTargetPath:" & driverTargetPath
    'Debug.Print Now & "driverOriginPath:" & driverOriginPath
    FileCopy driverTargetPath, driverOriginPath
    
    With testDriver
        'chrome(WebDriverまたはChromeDriver)の場合
        '.Start "chrome"
        
        'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
        .Start "MicrosoftEdge"

        .Get "http://www.yahoo.co.jp/"
        '.Quit
        .Close
    End With
End Sub

エラーのポイント・原因・対策

  • エラーになる「sample_test01」関数はグローバル変数を定義して「drivert.Close」を行っているが、closeしているのはブラウザ。グローバル変数のwebDriverはプログラム処理後、閉じてない。その状態でもう一度「sample_test01」関数を実行すると既に使っているとなりエラーとなる。
  • このエラーはGlobal変数(グローバル変数)を使っている場合に起こしやすい。
  • エラーにならない「sample_test02」関数は「drivert.Close」を利用してブラウザを閉じるだけしてwebDriverは閉じていないが、グローバル変数を利用していない為、関数終了時にwebDriverも破棄される。

対策

グローバル変数webDriverを利用する場合でも「driver.Quit」でブラウザの閉じとドライバーの破棄も行ってくれる。


Option Explicit

Dim testDriver As New Selenium.WebDriver

Public Sub sample_test03()
    'ChromeDriver | EdgeDriver | IEDriver | OperaDriver
    'FirefoxDriver | PhantomJSDriver
    'Dim testDriver As New Selenium.WebDriver
    Set testDriver = New Selenium.WebDriver
    
    Dim driverTargetPath:
    Dim driverOriginPath:
    
    'chrome(WebDriverまたはChromeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Chrome\86_0_4_40_22\chromedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\chromedriver.exe"

    'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
    driverTargetPath = "D:\Selenium\WebDriver\Microsoft_Edge\85_0_564_63\msedgedriver.exe"
    driverOriginPath = Environ$("LOCALAPPDATA") & "\SeleniumBasic\edgedriver.exe"
    
    'Debug.Print Now & "driverTargetPath:" & driverTargetPath
    'Debug.Print Now & "driverOriginPath:" & driverOriginPath
    FileCopy driverTargetPath, driverOriginPath
    
    With testDriver
        'chrome(WebDriverまたはChromeDriver)の場合
        '.Start "chrome"
        
        'MicrosoftEdge(WebDriverまたはEdgeDriver)の場合
        .Start "MicrosoftEdge"

        .Get "http://www.yahoo.co.jp/"
        '.Quit
        .Close
    End With
End Sub

備考

SeleniumBasicにはユーザーマニュアルがある。Selenium.chm。こちらに次のように書いてあります。

WebDriver.Close Method
Closes the current window.
翻訳:現在のウィンドウを閉じます。

Selenium.chm

WebDriver.Quit Method
Close the Browser and Dispose of WebDriver
翻訳:ブラウザを閉じてWebDriverを破棄します。

Selenium.chm

まとめ

今回はSeleniumBasicを例として取り上げましたが、他のことでも共通すると思います。グローバル変数でオブジェクトを使う場合は必ず閉じたか、正しく終了できたか、破棄できているか、確認する必要があります。

最後までお付き合いいただきありがとうございます!

この情報が誰かの役にたてれば幸いです。

スポンサーリンク

タグ

-その他

© 2021 BookALittle