Jump to content
Simpel

[work around] $oActiveWorkbook.UserStatus not working

Recommended Posts

Simpel

Hi.

I try to figure out who is using a excel workbook which I can only open "read only". I use this code:

#include <Array.au3>
#include <Excel.au3>
Local $sFile = ; excel file with path on a network drive

Local $oExcel = _Excel_Open(True, True)
Local $oTabelle = _Excel_BookOpen($oExcel, $sFile)
Local $aUsers
If IsObj($oTabelle) Then
    $aUsers = $oTabelle.UserStatus
    _ArrayDisplay($aUsers)
EndIf

If I am the one allowed to write to the excel file (I'm the first one who opened it) then I will get an array with myself:

UserStatus_Array.PNG.610210eb1edd63ae9956f14166a3fbcb.PNG

If my collegue opened the excel file first and I run the code I get the following error message:

"H:\_Conrad lokal\Downloads\AutoIt3\_COX\Tests\test.au3" (9) : ==> The requested action with this object has failed.:
$aUsers = $oTabelle.UserStatus
$aUsers = $oTabelle^ ERROR

The excel file is on a network drive. Is that's the problem?

Regards, Conrad

Edited by Simpel
[work around]

SciTE4AutoIt = 3.7.3.0   AutoIt = 3.3.14.2   AutoItX64 = 0   OS = Win7Pro SP1   OSArch = X64   Language = 0407/german
H:\...\AutoIt3\SciTE     H:\...\AutoIt3      H:\...\AutoIt3\Include     (H:\ = Network Drive)

   88x31.png  Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind.

Share this post


Link to post
Share on other sites
water

You need to add some kind of error checking to your script:

#include <Array.au3>
#include <Excel.au3>
Local $aUsers, $sFile = ; excel file with path on a network drive
Local $oExcel = _Excel_Open(True, True)
If @error Then Exit MsgBox(0, "Error", "Error " & @error & " opening Excel!")
Local $oTabelle = _Excel_BookOpen($oExcel, $sFile)
If @error Then Exit MsgBox(0, "Error", "Error " & @error & " opening Workbook!")
If @extended = 1 Then ; Workbook could not be opened as read/write
    $aUsers = $oTabelle.UserStatus
    _ArrayDisplay($aUsers)
EndIf

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Simpel

Hi @water,

currently I can't try it out (in the evening I can) but I think I will run into this error too. As I wrote I run into this error if the excel file is opened read only by me. Than @extended will be 1 and then $oTabelle.UserStatus will fail with object $oTabelle. Or am I wrong?

Conrad


SciTE4AutoIt = 3.7.3.0   AutoIt = 3.3.14.2   AutoItX64 = 0   OS = Win7Pro SP1   OSArch = X64   Language = 0407/german
H:\...\AutoIt3\SciTE     H:\...\AutoIt3      H:\...\AutoIt3\Include     (H:\ = Network Drive)

   88x31.png  Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind.

Share this post


Link to post
Share on other sites
water

Seems property UserStatus does not work the way we expect it to work.
Details and a solution can be found here: https://stackoverflow.com/questions/15555522/how-to-tell-if-an-excel-2007-spreadsheet-is-open-and-who-has-it-open-using-vbscr


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Simpel

Thanks @water for this hint. I couldn't find anything about it. This is my whole solution now:

#include <File.au3>
Local $sFile = ; fullpath to an excel file
Local $sOpened = _ExcelFileOpened($sFile)
If @error Then ; nobody has opened this excel file
    If @error = 1 Then
        ConsoleWrite("You can open the excel file and write to it." & @CRLF)
    ElseIf @error = 2 Then
        ConsoleWrite("File does not exist." & @CRLF)
    ElseIf @error = 3 Then
        ConsoleWrite("File ist not an excel file." & @CRLF)
    EndIf
ElseIf @extended = 1 Then
    ConsoleWrite("This excel file is already opened by you with write privilege" & @CRLF)
Else
    ConsoleWrite("This excel file is opened by " & $sOpened & @CRLF & "You can't write to the file therefor it will not be opened." & @CRLF)
EndIf
Exit


; #FUNCTION# ====================================================================================================================
; Name ..........: _ExcelFileOpened
; Description ...: Returns who has the excel file opened with write privilege
; Syntax ........: _ExcelFileOpened($sFile)
; Parameters ....: $sFile - must be an excel file
; Return values .: Success - name of who has opened the excel file with write privilege, sets @extended to:
;                  |1 - if I am the one
;                  Failure - 0, sets @error to:
;                  |1 - excel file is not opened
;                  |2 - file does not exist
;                  |3 - file is not an excel file
; Author ........: Simpel
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _ExcelFileOpened($sFile)
    ; check if file exists
    If FileExists($sFile) = 0 Then Return SetError(2, 0, 0)
    ; check if file is an excel file
    Local $iDelimiter = StringInStr($sFile, ".", 0, -1) ; splits suffix
    Local $sExtension = StringTrimLeft($sFile, $iDelimiter) ; only file extension
    If StringLeft($sExtension, 3) <> "xls" Then Return SetError(3, 0, 0)
    ; if excel has created a temporary excel file with a ~$ prefix then it is already opened
    $iDelimiter = StringInStr($sFile, "\", 0, -1) ; splits file from path
    Local $sTempFile = StringLeft($sFile, $iDelimiter) & "~$" & StringTrimLeft($sFile, $iDelimiter) ; adds prefix ~$ at excel filename
    Local $iTempFileExist = FileExists($sTempFile) ; if this file exists then the excel file is opened
    If $iTempFileExist = 0 Then Return SetError(1, 0, 0) ; is not opened
    Local $sOwnerTempFile = _Owner($sTempFile) ; owner of the excel temp file is the one with write privilege
    ; find out who I am
    Local $sTestFile = _TempFile() ; needs file.au3
    FileWrite($sTestFile, "") ; create a test file (I am definitely the owner)
    If @error Then
        Return $sOwnerTempFile ; returns only the one with write privilege to the excel file
    EndIf
    Local $sMe = _Owner($sTestFile) ; this is me
    FileDelete($sTestFile)
    ; look if I am the one created the temp excel file
    If $sOwnerTempFile = $sMe Then
        Return SetError(0, 1, $sMe) ; returns me opened excel file with write privilege and sets @extended to 1
    Else
        Return $sOwnerTempFile ; returns the one with write privilege to the excel file
    EndIf
EndFunc

Func _Owner($sFile) ; the one who saved it last - code by siao?
    Local $secUtil = ObjCreate("ADsSecurityUtility")
    Local $secDesc = $secUtil.GetSecurityDescriptor($sFile, 1, 1)
    Local $sOwner = $secDesc.Owner
    $secUtil = Null
    Return $sOwner
EndFunc

Regards, Conrad


SciTE4AutoIt = 3.7.3.0   AutoIt = 3.3.14.2   AutoItX64 = 0   OS = Win7Pro SP1   OSArch = X64   Language = 0407/german
H:\...\AutoIt3\SciTE     H:\...\AutoIt3      H:\...\AutoIt3\Include     (H:\ = Network Drive)

   88x31.png  Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind.

Share this post


Link to post
Share on other sites
water

Looks great!
Will test as soon as I find some spare time :)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • Gowrisankar
      By Gowrisankar
      Dear members of the forum,
      I need to open excel files that may or may not need a password and finally move the files that needs password to manual queue.
      Is there a fastest way to do this?
       
      PS: I have a huge respect for the rules of this forum. I am not asking assistance to override any security measure. I just need to segregate the files that needs passwords.
    • MrCheese
      By MrCheese
      Hi guys,
      without including everything (unless you want it)
      I am copying data from a table in chrome and wanting to paste it into excel.
      Copying in Chrome works.
      I can paste it into the field i want by emulating goto -> ctrl V:
      WinActivate($dataload) WinWaitActive($dataload) Sleep(500) $oWorkbook1.Sheets("ItemReturn").Activate Sleep(500) $msg = "Measuring Sheet" conwrite() ttips2() Local Const $xlUp = -4162 With $oWorkbook1.ActiveSheet ; process active sheet $oRangeLast = .UsedRange.SpecialCells($xlCellTypeLastCell) ; get a Range that contains the last used cells $iRowCount = .Range(.Cells(1, 1), .Cells($oRangeLast.Row, "B")).Rows.Count ; get the the row count for the range starting in row/column 1 and ending at the last used row/column $iLastCell = .Cells($iRowCount + 1, "B").End($xlUp).Row ; start in the row following the last used row and move up to the first used cell in column "B" and grab this row number EndWith $NewStartCell = $iLastCell + 2 $msg = "moving to location" conwrite() ttips2() Sleep(250) Send("^g") WinWait("Go To") Sleep(100) Send("B" & $NewStartCell) Sleep(100) Send("{ENTER}") Sleep(500) Send("^v")  
      But, I want to use _excel_rangecopypaste, pasting from the clipboard
      _Excel_RangeCopyPaste($oWorkbook1.ActiveSheet, default, "B" & $NewStartCell,default,$xlPasteValuesAndNumberFormats) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeCopy Example 2", "Error pasting cells." & @CRLF & "@error = " & @error & ", @extended = " & @extended) however, this gives me error 4 , extended@:  -2147352567
      How can i fix this or find out how to debug this error?
       
      Thanks
    • robertocm
      By robertocm
      change linked image paths in excel 2007 Open XML Files with AutoIt and 7-zip:
      #include <File.au3> ;Change this Local $sFind = "C:\Users\MyUserName\Documents\MyImageFolder\My%20Image1.png" Local $sReplace = "C:\Users\ANOTHERUSERNAME\Documents\AnotherImageFolder\My%20Image1.png" Local Const $sMessage = "Directory to change excel image paths" Local $sFileSelectFolder = FileSelectFolder($sMessage, "") Local $sTempDir = @ScriptDir & "\testdir" ;Required 7-zip Local $PathZipProgram = @ProgramFilesDir & "\7-Zip\" If Not(FileExists($PathZipProgram & "\7z.exe")) Then MsgBox(16, "", "7z.exe not found in path " & $PathZipProgram) Exit EndIf ;look for excel files in selected directory and all subdirectories Local $SFileList = _FileListToArrayRec($sFileSelectFolder, "*.xls.;*.xlsm", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) If Not @error Then For $i = 1 To $SFileList[0] DirRemove($sTempDir, 1) ;use x command to keep the folder stucture, -aoa Overwrite All existing files without prompt, use -r to unzip the subfolders from the zip file RunWait('"' & $PathZipProgram & '7z.exe" x -aoa -r "' & $SFileList[$i] & '" -o"' & $sTempDir & '" -y', $PathZipProgram, @SW_HIDE) __ReplaceImagePaths($sTempDir, $sFind, $sReplace) RunWait('"' & $PathZipProgram & '7z.exe" a -r "' & $SFileList[$i] & '" "' & $sTempDir & '\*" -tzip -y', $PathZipProgram, @SW_HIDE) Next Else MsgBox(16, "Error", "No files were found in the folder specified.") EndIf DirRemove($sTempDir, 1) Func __ReplaceImagePaths($sTempDir, $sFind, $sReplace) ;List all files with .xml.rels extension in the directory \xl\drawings\_rels Local $aFileList = _FileListToArray($sTempDir & "\xl\drawings\_rels", "*.xml.rels", 1, True) If @error = 1 Then ;MsgBox (0, "", "Path was invalid") SplashTextOn("Title", "Path was invalid", -1, -1, -1, -1, 1, "", 24) Sleep(2000) SplashOff() Exit EndIf If @error = 4 Then ;MsgBox (0, "No files", "No files were found") SplashTextOn("Title", "No files were found", -1, -1, -1, -1, 1, "", 24) Sleep(2000) SplashOff() Exit EndIf Local $iRetval ;Loop through the array For $i = 1 To $aFileList[0] $iRetval = _ReplaceStringInFile($aFileList[$i], $sFind, $sReplace) Next EndFunc  
      Some references:
      https://stackoverflow.com/questions/37145369/change-path-to-picture-links-in-excel http://www.jkp-ads.com/Articles/Excel2007FileFormat.asp EDITED:
      Note: it seems that if User Account Control (UAC) is enabled then 7zip is unable to overwrite the destination file (using the same name).
      In this case, a possible solution would be to rename the original excel file before (see _PathSplit in help file).
      In my case i prefer just to disable UAC
    • SOF-TECH
      By SOF-TECH
      Dear all,
      Can someone show  me how to en hance the below function to write in CSV  into column  and rows the input values ? 
      I am getting this result: 

      I would like the result to be as this 

      From A1:C1 is for headers
      From A2:C2 is for input Data
      Global Const $GUI_EVENT_CLOSE = -3 $sDataFilePath = @ScriptDir & "\Records.csv" #region ### START Koda GUI section ### Form= $Form1 = GUICreate("Demo1: New Record", 580, 115) $Input1 = GUICtrlCreateInput("", 10, 30, 270, 21) $Input2 = GUICtrlCreateInput("", 300, 30, 270, 21) $Input3 = GUICtrlCreateInput("", 10, 80, 270, 21) $Label1 = GUICtrlCreateLabel("Name:", 10, 10, 35, 17) $Label2 = GUICtrlCreateLabel("ID:", 300, 10, 18, 17) $Label3 = GUICtrlCreateLabel("Phone No:", 10, 60, 55, 17) $Button1 = GUICtrlCreateButton("Save to CSV", 450, 70, 120, 30) GUISetState(@SW_SHOW) #endregion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $Button1 _ExportData() MsgBox(64, @ScriptName, "Record Saved.") EndSwitch WEnd Func _ExportData() If Not FileExists($sDataFilePath) Then FileWriteLine($sDataFilePath, "Name;ID;Phone No.;") EndIf For $i = $Input1 To $Input3 FileWrite($sDataFilePath, GUICtrlRead($i) & ";") Next FileWriteLine($sDataFilePath, "") EndFunc ;==>_ExportData May be Excel UDF has be to be added but I can manage that my self  
      Thank you in advance
    • MrCheese
      By MrCheese
      HI there
      this is driving me nuts - i get the row count, but not the column count - what am I missing? Thanks for your help!
      #include <Excel.au3> #include <Array.au3> #include <MsgBoxConstants.au3> ; XlDirection enumeration: https://msdn.microsoft.com/en-us/library/office/ff820880.aspxGlobal $oExcel = _Excel_Open() Global $xlup = -4162 Global $xlByRows, $xlPrevious, $xlByColumns Global $oExcel = _Excel_Open() $bookname = "temp.xlsx" $sWorkbook = @ScriptDir & "\" & $bookname Global $oWorkbook = _Excel_BookOpen($oExcel, $sWorkbook, Default, Default, True) With $oWorkbook.ActiveSheet ; process active sheet $oRangeLast = .UsedRange.SpecialCells($xlCellTypeLastCell) ; get a Range that contains the last used cells $iRowCount = .Range(.Cells(1, 1), .Cells($oRangeLast.Row, $oRangeLast.Column)).Rows.Count ; get the the row count for the range starting in row/column 1 and ending at the last used row/column $iColCount = .Range(.Cells(1, 1), .Cells($oRangeLast.Row, $oRangeLast.Column)).Column.Count MsgBox(0, "", "row:" & $iRowCount & "Col:" & $iColCount) EndWith  
      for context - i want to :
      * count columns used in excel
      * create ini file from the rows in each column - finishing at the last column used - i.e. one column for one ini file; containing 15 rows or so.
      is it better to read the entire sheet to an array via the sheettoarray function? then read it from that?
       
       
      temp.xlsx
×