Check if a file exists faster than OPEN DATASET - performance

I'm searching for a way to check if a file exists before using the OPEN DATASET command to open it. The OPEN DATASET command takes up to 30 seconds to trigger an exception, which is too slow for my liking.
This is the code:
TRY.
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE
ENCODING DEFAULT
WITH SMART LINEFEED.
CONCATENATE ` ` lv_resultdata INTO lv_resultdata.
TRANSFER lv_resultdata TO lv_file.
CLOSE DATASET lv_file.
CATCH cx_sy_file_access_error.
MESSAGE 'Placeholder-message. File cannot be reached'.
EXIT.
ENDTRY.

Try this:
DATA: filepath TYPE epsf-epsdirnam VALUE '/tmp'.
CALL FUNCTION 'EPS_GET_DIRECTORY_LISTING'
EXPORTING
dir_name = filepath
file_mask = 'somefile.txt'
EXCEPTIONS
invalid_eps_subdir = 1
sapgparam_failed = 2
build_directory_failed = 3
no_authorization = 4
read_directory_failed = 5
too_many_read_errors = 6
empty_directory_list = 7
OTHERS = 8.
CHECK sy-subrc = 0.
" writing dataset
It can also be used for remote servers.

Related

Assign File.readlines[n] to variable

I'm reading a text file which has instructions on each line. I want to assign the text on each line to it's own variable. When I do this, the value returned is nil but when I output the value of readlines[n] it is correct.
e.g.
# Using the variable (incorrect result)
puts current_zone_size
>
e.g.
# Using readlines after variable assignment (incorrect result)
current_zone_size = instructions.readlines[0]
instructions.readlines[0]
>
e.g.
# Using readlines (correct result)
instructions.readlines[0]
> 8 10
This is my code:
instructions = File.open("operator-input.txt", "r")
current_zone_size = instructions.readlines[0]
rover_init_location_orientation = instructions.readlines[1]
rover_movements = instructions.readlines[2]
This is the text in the file being read:
8 10
1 2 E
MMLMRMMRRMML
Edit:
Is the file being closed? Is this the reason I can't assign values from File.readlines[n] to variables if I'm not doing the variable assignment from within a block?
Also, the file will only ever have three lines which is why I'm not using a loop to read the lines.
IO#readlines reads all the lines in the file. It should not come as a surprise that, in order to read all the lines in the file, it has to read the entire file.
So, where is the file pointer after you read the entire file? It is at the end of the file.
What happens if you call IO#readlines the second time, when the file pointer is still at the end of the file? It will start reading at the position of the file pointer, which means it will read an empty file.
Therefore, if you want to do it the way you are doing it, you need to reset the file pointer to the beginning of the file every time you call IO#readlines:
instructions = File.open('operator-input.txt', 'r')
current_zone_size = instructions.readlines[0]
instructions.pos = 0
rover_init_location_orientation = instructions.readlines[1]
instructions.pos = 0
rover_movements = instructions.readlines[2]
Note also that you are leaking resources: you never close the file, so it will only by closed at the earliest by Ruby when the instructions variable gets out of scope and the File instance gets garbage-collected, and at the latest by the OS automatically when your Ruby process exits, which may be a long time later. So, your code should rather be:
instructions = File.open('operator-input.txt', 'r')
current_zone_size = instructions.readlines[0]
instructions.pos = 0
rover_init_location_orientation = instructions.readlines[1]
instructions.pos = 0
rover_movements = instructions.readlines[2]
instructions.close
In general, it is much better to use the block form of File::open, which closes the file handle automatically for you at the end of the block, and also ensures that this happens even in the case of complex control flow, errors, or exceptions:
File.open('operator-input.txt', 'r') do |instructions|
current_zone_size = instructions.readlines[0]
instructions.pos = 0
rover_init_location_orientation = instructions.readlines[1]
instructions.pos = 0
rover_movements = instructions.readlines[2]
end
Note, however, that what you want to do is horribly inefficient: you read the entire file, then take the first line, throw the rest away. Then you read the entire file again, take the second line, throw the rest away. Then you read the entire file again, take the third line, throw the rest away.
It makes much more sense to read the entire file once and then take the lines you need. Something like this:
File.open('operator-input.txt', 'r') do |instructions|
current_zone_size, rover_init_location_orientation, rover_movements =
instructions.readlines
end
However, in the case where all you do is open the file, read all lines, then immediately close it again, you should rather use the IO::readlines method instead of IO#readlines, since it does all three things for you in one call:
current_zone_size, rover_init_location_orientation, rover_movements =
File.readlines('operator-input.txt')
I ended up reading all the lines at once, now I'm able to set each variable outside of a block. Like this:
instructions = File.readlines "operator-input.txt"
current_zone_size = instructions[0]
rover_init_location_orientation = instructions[1]
rover_movements = instructions[2]
e.g.
puts current_zone_size
> 8 10

Having trouble with a vbscript creating a new vbscript containing a variable from the original

I am trying to make a vbs that creates a new vbs file, but im having some trouble with the creation of the second file.
Earlier in the first script it asks for your desired username, which is then assigned to a variable named user.
When it creates the second script, i want the user name to display in a message saying Welcome back [insert username here]. Please input a program value.
problem is, i cant get it to place your username inside of the new scripts code.
attempt 1
If VTCreate1 = 6 And VTCreate2 = 7 And VTCreate3 = 7 And VTCreate4 = 7 And VTCreate5 = 7 Then
Set objFile = objFS.CreateTextFile("C:\Users\Public\Desktop\Aeshnidae_1627374757.vbs")
objFile.WriteLine("vtcmd=inputbox(""Welcome back "")" & user & "("". Please input a program value."")")
attempt 1 results in the newly created script containing the following
vtcmd=inputbox("Welcome back ")Human(". Please input a program value.")
attempt 2
If VTCreate1 = 6 And VTCreate2 = 7 And VTCreate3 = 7 And VTCreate4 = 7 And VTCreate5 = 7 Then
Set objFile = objFS.CreateTextFile("C:\Users\Public\Desktop\Aeshnidae_1627374757.vbs")
objFile.WriteLine("vtcmd=inputbox(""Welcome back & user & . Please input a program value."")")
attempt 2 results in the following
vtcmd=inputbox("Welcome back & user & . Please input a program value.")
any idea how to get the desired username properly inside of the message?
Let's start with the final desired output line
vtcmd=inputbox("Welcome back xxxxxx. Please input a program value")
To place it inside a string variable (what we will later write) we need to quote the line and escape inner double quotes
"vtcmd=inputbox(""Welcome back xxxxxx. Please input a program value"")"
To replace the placeholder we need to cut our string
"vtcmd=inputbox(""Welcome back " ". Please input a program value"")"
close quote ^ ^ open quote
And concatenate the variable with the two strings
"vtcmd=inputbox(""Welcome back " & user & ". Please input a program value"")"
So, the final code line will be
objFile.WriteLine "vtcmd=inputbox(""Welcome back " & user & ". Please input a program value"")"

VBScript Error 52 Bad file name or number

I have a VBScript which is used in Avaya CMS to generate a CSV every 3 seconds. This CSV is then read on each change by a node server.
Every now and then it will throw an error (Error 52) and it then requires someone to manually click OK on the prompt and then it continues.
I didn't write the initial script, but I have been trying to fix it so it doesn't throw this error.
As far as I understand, the issue is being caused when the script tries to write to the file when the node server is trying to read the file.
So far I have tried to fix this by making the file read only, then, in the script it makes it writeable, writes to it and makes it read only again.
I thought this had fixed the issue, but I have received Error 52 pop up again and now I am unsure.
Does anyone know if there is a way to get VB/Avaya to ignore the error? I was thinking something like putting On Error Resume Next before the line that writes the file?
I know ignoring errors is not good practice, but in this case, if it does ignore it, it just means the file wont be updated on this loop, but 3 seconds later it will loop again so it should be fine.
Script:
On Error Resume Next
cvsSrv.Reports.ACD = 1
Set Info = cvsSrv.Reports.Reports("Real-Time\Designer\Skill Status")
If Info Is Nothing Then
Else
b = cvsSrv.Reports.CreateReport(Info,Rep)
If b Then
Rep.RefreshInterval = 3
Rep.SetProperty "Split/Skill","5"
Set WshShell = CreateObject("WScript.Shell")
theHTMLLocation = "C:\wamp\www\wallboards\agent_status.csv"
theSleepFile = "C:\wamp\www\wallboards\sleep.vbs"
theTemplateLocation = ""
Set fso = CreateObject("Scripting.FileSystemObject")
Set gfile = fso.GetFile("C:\wamp\www\wallboards\agent_status.csv")
Do While Rep.Window.Caption <> ""
gfile.Attributes = 0
d = Rep.ExportData("C:\wamp\www\wallboards\agent_status.csv", 44, 0, False, True, True)
gfile.Attributes = 1
WshShell.Run "wscript.exe """ & theSleepFile & """", , True
Loop
If Not cvsSrv.Interactive Then cvsSrv.ActiveTasks.Remove Rep.TaskID
Set Rep = Nothing
End If
End If
Set Info = Nothing
P.S - I left out some Parameters at that start of the file which I don't think are relevant, if someone thinks they are I will add them.

WinCC export screen data to xls/csv

I am using TIA portal V13, with WinCC RT Advanced. I have been given a running project and need to export some values to excel for the client daily, monthly and yearly using a script. I have a screen with a table control that displays values of tags. The values are logged periodically.
How can I access the values from the screen or data logs using vbs? There is this command in the manual for accessing the dataLogs
HMIRuntime.Logging.DataLogs
But I cannot find how to access the data and save it to a file.
There is already a vbs script in the project(begin and end times are defined earlier in the script)but it just exports an empty csv with the column names but no values.
Set obj1 = obj.ScreenItems("Table view_1")
obj1.TimeColumnRangeType = 1
obj1.TimeColumnBeginTime = sBeginTime
obj1.TimeColumnEndTime = sEndTime
FolderName = "C:\Folder_name"
FileDate = sDay &"_" &sMonth &"_" &sYear
obj1.ExportDirectoryChangeable = True
obj1.ExportDirectoryname = FolderName
obj1.ExportFilenameChangeable = True
obj1.ExportFilename = "Filename " &FileDate
obj1.Export()

0x800a0005 Error when using OpenAsTextStream

My intention is to write every output line to a log file for archive purposes. Instead of writing to a file using OpenTextFile() and Write(), and then closing at the end of the script, I would like to write to the file as the script executes. If for whatever reason, the script is terminated before it has a chance to close the file, I worry I will lose those logs.
To achieve this, here is what I have attempted:
'Master Logs
Dim MasterLogFileName, MasterLogFile, MasterLogFileStream
Const ForAppending = 8
Const TristateUseDefault = 2
Function Write(text)
Wscript.StdOut.Write text
Set MasterLogFileStream = MasterLogFile.OpenAsTextStream(ForAppending, TristateUseDefault)
MasterLogFileStream.Write text
MasterLogFileStream.Close
End Function
'Create a Master Log file to write to
MasterLogFileName = "LogFile.log"
fso.CreateTextFile(MasterLogFileName)
Set MasterLogFile = fso.GetFile(MasterLogFileName)
Write("Test writing!")
Write("Test writing 2!")
However, I receive the following error:
0x800a005 - Microsoft VBScript runtime error: Invalid procedure call or argument
On this line:
Set MasterLogFileStream = MasterLogFile.OpenAsTextStream(ForAppending, TristateUseDefault)
When executing the Write() Function for the second time, using this line:
Write("Test writing 2!")
As specified by Lankymart and JosefZ, the reason this wasn't working was because I specified 2 for TristateUseDefault, instead of -2, as per the OpenAsTextStream method specifies.

Resources