I am trying to run a R script from excel VBA. The script just queries data, formats and organizes it, and then exports it as a separate XLS file. However, I can not get the R script to run.
Going off of this post: (albeit the OG code is what I understood)
Running R from Excel VBA without RExcel
I don't have access to RExcel due to work restrictions on downloads. I have found my R.exe file paths and the macro below is able to run:
Dim rCommand As String
rCommand = "C:\Program Files\R\R-3.5.3\bin\R.exe --verbose U:\Reporting\Mix of Business Report\Morgan's Trials\Mix of Business Report v1.R"
'Timer Set to run full Model.R script
Application.Wait Now + TimeValue("00:01:05")
'Runs R Script and Arguments into process
shell rCommand, vbNormalFocus
'Timer Set to run full Model.R Script
Application.Wait Now + TimeValue("00:01:05")
I wanted my macro to run in the background, however the R window (NOT Rstudio, which is fine, as long as it works) doesn't run the R script.
Here is what I am shown in the "Rterm" window:
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.
ARGUMENT 'U:\Reporting\Mix' __ ignored__
ARGUMENT 'of' __ ignored__
ARGUMENT 'Business' __ ignored__
ARGUMENT 'Report\Morgan's' __ ignored__
ARGUMENT 'Trials\Mix' __ ignored__
ARGUMENT 'of' __ ignored__
ARGUMENT 'Business' __ ignored__
ARGUMENT 'Report' __ ignored__
ARGUMENT 'v1.R' __ ignored__
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("C:/Program Files/R/R-3.5.3/library/methods/libs/x64/methods.dll") ...
'verbose' and 'quietly' are both true; being verbose then ..
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("C:/Program Files/R/R-3.5.3/library/utils/libs/x64/utils.dll") ...
'verbose' and 'quietly' are both true; being verbose then ..
Garbage collection 1 = 0+0+1 (level 2) ...
11.5 Mbytes of cons cells used (35%)
2.7 Mbytes of vectors used (4%)
now dyn.load("C:/Program Files/R/R-3.5.3/library/grDevices/libs/x64/grDevices.dll") ...
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("C:/Program Files/R/R-3.5.3/library/graphics/libs/x64/graphics.dll") ...
'verbose' and 'quietly' are both true; being verbose then ..
now dyn.load("C:/Program Files/R/R-3.5.3/library/stats/libs/x64/stats.dll") ...
ending setup_Rmainloop(): R_Interactive = 1 {main.c}
>R_ReplConsole(): before "for(;;)" {main.c}
Why is my file path being ignored? I also tried changing the backslashes of my verbose r script path to forward slashes, same message.
Sorry if it's repetitive, I don't understand any of the other questions posted and the one linked above was my best shot.
It seems like the problem is in the path, because in UNC you need to put quotes in a path that contains spaces. Change the command like this and it will work:
Dim rCommand As String
rCommand = """C:\Program Files\R\R-3.5.3\bin\R.exe"" --verbose ""U:\Reporting\Mix of Business Report\Morgan's Trials\Mix of Business Report v1.R"""
Edit
Another problem was that R.exe shouldn't be used to simply execute scripts. We can use RScript.exe for that purpose and we can avoid the console closing, by adding && pause at the end of the command. Here's the complete code:
Dim rCommand As String
rCommand = """C:\Program Files\R\R-3.5.3\bin\RScript.exe"" --verbose ""U:\Reporting\Mix of Business Report\Morgan's Trials\Mix of Business Report v1.R"" && pause"
'Timer Set to run full Model.R script
Application.Wait Now + TimeValue("00:01:05")
'Runs R Script and Arguments into process
Shell rCommand, vbNormalFocus
'Timer Set to run full Model.R Script
Application.Wait Now + TimeValue("00:01:05")
Sync Method
A way to improve the function is to execute the shell with waitTillComplete flag, which executes the command with a Sync call. Here's the code:
Sub R_Exec()
Dim cmd As Object
Dim rCommand As String, rBin As String, rScript As String
Dim errorCode As Integer
Dim waitTillComplete As Boolean: waitTillComplete = True
Dim debugging As Boolean: debugging = True
Set cmd = VBA.CreateObject("WScript.Shell")
rBin = """C:\Program Files\R\R-3.5.3\bin\RScript.exe"""
rScript = """U:\Reporting\Mix of Business Report\Morgan's Trials\Mix of Business Report v1.R"""
'Check if the shell has to keep CMD window or not
If debugging Then
rCommand = "cmd.exe ""/k"" " & rBin & " " & rScript
Else
rCommand = rBin & " " & rScript
End If
Debug.Print rCommand 'Print the command for debug
'Runs R Script and Arguments into process, returning errorCode
errorCode = cmd.Run(rCommand, vbNormalFocus, waitTillComplete)
End Sub
With this Sub you can decide if keep the shell window open or not.
Hope this helps.
Alternatively, for cleaner code to avoid too many quote handling and extendable to many arguments consider building command line call from an array of arguments (borrowed from #UriGoren). Also, use CMD.exe /k to launch window of the automated Rscript (which ideally should be accessible through the PATH environment variable):
Sub Run_R_Script()
Dim args(0 To 3) As String
Dim rCommand As String
Dim i As Integer
args(0) = "CMD.exe"
args(1) = "/k"
'args(2) = "Rscript.exe" ' IF R BIN FOLDER IN PATH ENV VARIABLE
args(2) = "C:\Program Files\R\R-3.5.3\bin\RScript.exe"
args(3) = "U:\Reporting\Mix of Business Report\Morgan's Trials\Mix of Business Report v1.R"
rCommand = args(0)
For i = 1 To UBound(args)
rCommand = rCommand & " """ & args(i) & """"
Next i
Debug.Print rCommand ' CHECK COMMAND LINE CALL
'Timer Set to run full Model.R script
Application.Wait Now + TimeValue("00:01:05")
'Runs R Script and arguments into process
Shell rCommand, vbNormalFocus
'Timer Set to run full Model.R Script
Application.Wait Now + TimeValue("00:01:05")
End Sub
Related
i'm new to nf-core/nextflow and needless to say the documentation does not reflect what might be actually implemented. But i'm defining the basic pipeline below:
nextflow.enable.dsl=2
process RUNBLAST{
input:
val thr
path query
path db
path output
output:
path output
script:
"""
blastn -query ${query} -db ${db} -out ${output} -num_threads ${thr}
"""
}
workflow{
//println "I want to BLAST $params.query to $params.dbDir/$params.dbName using $params.threads CPUs and output it to $params.outdir"
RUNBLAST(params.threads,params.query,params.dbDir, params.output)
}
Then i'm executing the pipeline with
nextflow run main.nf --query test2.fa --dbDir blast/blastDB
Then i get the following error:
N E X T F L O W ~ version 22.10.6
Launching `main.nf` [dreamy_hugle] DSL2 - revision: c388cf8f31
Error executing process > 'RUNBLAST'
Error executing process > 'RUNBLAST'
Caused by:
Not a valid path value: 'test2.fa'
Tip: you can replicate the issue by changing to the process work dir and entering the command bash .command.run
I know test2.fa exists in the current directory:
(nfcore) MN:nf-core-basicblast jraygozagaray$ ls
CHANGELOG.md conf other.nf
CITATIONS.md docs pyproject.toml
CODE_OF_CONDUCT.md lib subworkflows
LICENSE main.nf test.fa
README.md modules test2.fa
assets modules.json work
bin nextflow.config workflows
blast nextflow_schema.json
I also tried with "file" instead of path but that is deprecated and raises other kind of errors.
It'll be helpful to know how to fix this to get myself started with the pipeline building process.
Shouldn't nextflow copy the file to the execution path?
Thanks
You get the above error because params.query is not actually a path value. It's probably just a simple String or GString. The solution is to instead supply a file object, for example:
workflow {
query = file(params.query)
BLAST( query, ... )
}
Note that a value channel is implicitly created by a process when it is invoked with a simple value, like the above file object. If you need to be able to BLAST multiple query files, you'll instead need a queue channel, which can be created using the fromPath factory method, for example:
params.query = "${baseDir}/data/*.fa"
params.db = "${baseDir}/blastdb/nt"
params.outdir = './results'
db_name = file(params.db).name
db_path = file(params.db).parent
process BLAST {
publishDir(
path: "{params.outdir}/blast",
mode: 'copy',
)
input:
tuple val(query_id), path(query)
path db
output:
tuple val(query_id), path("${query_id}.out")
"""
blastn \\
-num_threads ${task.cpus} \\
-query "${query}" \\
-db "${db}/${db_name}" \\
-out "${query_id}.out"
"""
}
workflow{
Channel
.fromPath( params.query )
.map { file -> tuple(file.baseName, file) }
.set { query_ch }
BLAST( query_ch, db_path )
}
Note that the usual way to specify the number of threads/cpus is using cpus directive, which can be configured using a process selector in your nextflow.config. For example:
process {
withName: BLAST {
cpus = 4
}
}
I use the following script to import a module into an excel file using an on Stack Overflow on the same topic.
I first exported the module from another excel file as "Module1.bas"). However, it gives me an exception error (in German on my notebook: Error: Ausnahmefehler aufgetreten), when I run the line:
xlWbk$VBProject()$VBComponents()$Import("C:/git/bl_publ/scripts/Module1.bas")
Anyone an idea, why this is not working (the paths are correct)?
The script looks like this:
library(librarian)
library(RDCOMClient)
# Kill any existing Excel processes
try(system("Taskkill /IM Excel.exe /F"),silent = TRUE)
# Open a specific workbook in Excel:
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open("C:/git/bl_publ/scripts/temp.xlsx")
xlWbk$VBProject()$VBComponents()$Import("C:/git/bl_publ/scripts/Module1.bas")
# this line of code might be necessary if you want to see your spreadsheet:
xlApp[['Visible']] <- TRUE
# Run the macro called "MyMacro":
xlApp$Run("macro2")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWbk, xlApp)
gc()
The bas-file looks like this:
Attribute VB_Name = "Module1"
'
Sub Macro1()
'
' Macro1 Macro
'
'
ChDir "C:\git\bl_publ\scripts"
ActiveWorkbook.SaveAs Filename:="C:\git\bl_publ\scripts\macro.xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End Sub
Sub Macro2()
Attribute Macro2.VB_ProcData.VB_Invoke_Func = " \n14"
'
' Macro2 Macro
'
Cells.Replace What:="999999", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Cheers
Renger
I am trying to run some autoit.au3 script from command line and see results there. I have put some ConsoleWrite inside script and also Exit(1) but after I run script nothing is shown in console. It just stop script on Exit and ConsoleWrite is not displayed.
I have use command:
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3"'
Also I have tried to run script.exe with this same command but with similar (no) result. I would like to see output in console and/or custom error messages when script fail (I don't know if that is possible).
AutoIt3.exe is a GUI program. So the STD streams of a GUI program are not printed at a console by default.
The /ErrorStdOut argument redirects errors messages to Console instead of a Msgbox.
This argument does not enable print at the Console.
Command Prompt:
To print at a Command Prompt, you could pipe to more, i.e.
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3" 2>&1|more
more reads from the Stdin stream and prints to Console.
I intentionly added 2>&1 so the Stderr stream is merged with
Stdout so you get the merged streams printed.
If you do not want the errors, then you can redirect the Stderr stream to nul i.e.
replace 2>&1 with 2>nul.
If you used a for loop at a Command Prompt, it would be i.e.
for /f "delims=" %A in ('"C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
If you use the for loop in batch-file, use %%A instead of %A. To also capture the Stderr, insert 2^>&1 into the for command or to ignore, insert 2^>nulinto the for command i.e.
for /f "delims=" %A in ('2^>nul "C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
The previous methods will not get the Exitcode.
AutoIt code:
An AutoIt script can get the Stdout and the Exitcode.
#pragma compile(Out, 'consoleau3.exe')
#pragma compile(Console, True)
$sAutoit = 'C:...(path to my AutoIt3.exe)'
$iPid = Run('"' & $sAutoit & '" /ErrorStdout ' & $CMDLINERAW, '', #SW_SHOW, 2) ; 2 = Get Stdout stream.
If #error Then Exit
; Open process handle.
$hPid = _ProcessOpenHandle($iPid)
; Get Stdout stream and then print to Console.
$sStdout = ''
Do
Sleep(10)
If $sStdout Then ConsoleWrite($sStdout & #CRLF)
$sStdout = StdoutRead($iPid)
Until #error
; Require process to be closed before calling _ProcessGetExitCode()
ProcessWaitClose($iPid)
; Get exitcode of process.
$iExitcode = _ProcessGetExitCode($hPid)
; Close process handle.
_ProcessCloseHandle($hPid)
Exit $iExitcode
Func _ProcessOpenHandle($iPID)
; Get the process handle of the process to query\n Return: Success Handle as array. Failure 0
Local Const $PROCESS_QUERY_INFORMATION = 0x400
Local $hPID = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', $PROCESS_QUERY_INFORMATION, 'int', 0, 'int', $iPID)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[0]
EndFunc
Func _ProcessGetExitcode($hPID)
; Get exitcode of the closed process\n Return: Success Exitcode as integer. Failure 0
Local $vPlaceholder
$hPID = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $hPID, 'int*', $vPlaceholder)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[2]
EndFunc
Func _ProcessCloseHandle($hPID)
; Close the handle of a process\n Return: Success 1. Failure 0
DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $hPID)
If #error Then Return SetError(#error, #extended, 0)
Return 1
EndFunc
Correct the path to AutoIt.exe in the code.
Compile to AutoIt code to executable. It will be a Console program
and will be named consoleau3.exe as to the #pragma compile directives.
Usage:
consoleau3 "path_to_my_script.au3"
Script arguments can be added i.e.
consoleau3 "path_to_my_script.au3" arg1 arg2 arg3 ...
I am trying to use following cmd function inside R
rmdir /q /s myDir
I tried:
system("rmdir /q /s myDir")
but it returns an error:
rmdir: failed to remove '/q': No such file or directory
rmdir: failed to remove '/s': No such file or directory
rmdir: failed to remove 'public_html/croecon.contentio.biz': Directory not empty
How should I use slash option, e.g. /q?
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery("SELECT * FROM Win32_ProcessStartTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process where ProcessID=" & objReceivedEvent.ProcessID)
For Each objItem in colItems
wscript.echo objItem.name & " " & objItem.ProcessID & " " & objItem.CommandLine
Next
Loop
Then type in a command prompt
cscript //nologo C:\folder\MonitorProcessCreation.vbs
This will monitor what starts when you run your command.
I am trying to run external tools from the MEME suite, one of this tool (jaspar2meme) producing a text file that is then use as an input of a second tool (fimo). Here is my code :
#!usr/bin/Rscript
com1 <- "meme/bin/jaspar2meme"
arg1 <- "-bundle jaspar_plant_2014.pfm"
message("jaspar2meme command: ", com1, arg1)
system2(command = com1, args = arg1, stdout = "motif.fimo", wait = T)
com2 <- paste0("meme/bin/fimo")
arg2 <- paste0("--text --oc . --verbosity 1 --thresh 1.0E-4 --bgfile bg.fimo motif.fimo Genes_up_h16.ame")
message("FIMO command: ", com2, arg2)
system2(command = com2, args = arg2, stdout = "fimoresult.txt", wait = T)
When I run this code from within RStudio (via source), it works perfectly: the file motif.fimo is produced by jaspar2meme and use by fimo to produce the resulting file fimoresult.txt.
When I run the same script via Rscript from the shell (bash), the motif.fimo is also produced as expected but is not found by fimoand the fimoresult.txt remains empty.
What I tried so far is to use either system() or system2(), using the wait=T option or not, specifying the full path to motif.fimo but without success.
I finally got it... The locale variables were different in RStudio and Rscript. The motif.fimo file produced by jaspar2meme looked the same in both cases but was apparently not. By changing the first call to system2() by :
system2(command = com1, args = arg1, stdout = "motif.fimo", wait = T, env = c("LC_NUMERIC=C"))
solve my problem.