英文:
R: Run VBA function from R
问题
I am working with the R programming language.
我正在使用R编程语言。
I have the following dataset:
我有以下数据集:
df = structure(list(var1 = c(4.39524353447787, 7.6982251051672, 25.5870831414912,
10.7050839142458, 11.2928773516095, 27.1506498688328, 14.609162059892,
-2.65061234606534, 3.13147148106474, 5.54338029900042), var2 = c(22.2408179743946,
13.5981382705736, 14.0077145059405, 11.1068271594512, 4.44158865245925,
27.8691313680308, 14.9785047822924, -9.66617156629638, 17.0135590156369,
5.27208592272066), var3 = c(-0.678237059868451, 7.82025085341705,
-0.260044483072397, 2.7110877070886, 3.74960732150743, -6.86693310742413,
18.3778704449452, 11.5337311783652, -1.38136937011948, 22.5381492106993
), var4 = c(14.2646422147681, 7.04928517007729, 18.9512566104502,
18.7813348753304, 18.2158108163749, 16.8864025410009, 15.5391765353759,
9.38088289423278, 6.94037336260083, 6.19528998987617)), row.names = c(NA,
-10L), class = "data.frame")
write.csv(df, "df.csv")
这是我的数据集:
df = structure(list(var1 = c(4.39524353447787, 7.6982251051672, 25.5870831414912,
10.7050839142458, 11.2928773516095, 27.1506498688328, 14.609162059892,
-2.65061234606534, 3.13147148106474, 5.54338029900042), var2 = c(22.2408179743946,
13.5981382705736, 14.0077145059405, 11.1068271594512, 4.44158865245925,
27.8691313680308, 14.9785047822924, -9.66617156629638, 17.0135590156369,
5.27208592272066), var3 = c(-0.678237059868451, 7.82025085341705,
-0.260044483072397, 2.7110877070886, 3.74960732150743, -6.86693310742413,
18.3778704449452, 11.5337311783652, -1.38136937011948, 22.5381492106993
), var4 = c(14.2646422147681, 7.04928517007729, 18.9512566104502,
18.7813348753304, 18.2158108163749, 16.8864025410009, 15.5391765353759,
9.38088289423278, 6.94037336260083, 6.19528998987617)), row.names = c(NA,
-10L), class = "data.frame")
write.csv(df, "df.csv")
Here is a VBA function I have that I am running from the VBA editor within Excel:
以下是我在Excel的VBA编辑器中运行的VBA函数:
Sub ColorCellsRowWise()
Dim myRange As Range
Set myRange = Range("A2:D11")
Dim row As Range
For Each row In myRange.Rows
Dim cell As Range
For Each cell In row.Cells
If IsNumeric(cell.Value) Then
If cell.Value = Application.WorksheetFunction.Max(row) Then
cell.Interior.Color = RGB(253, 127, 127)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 2) Then
cell.Interior.Color = RGB(252, 181, 128)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 3) Then
cell.Interior.Color = RGB(253, 247, 127)
Else
cell.Interior.Color = RGB(199, 254, 126)
End If
End If
Next cell
Next row
End Sub
这是我在Excel的VBA编辑器中运行的VBA函数:
Sub ColorCellsRowWise()
Dim myRange As Range
Set myRange = Range("A2:D11")
Dim row As Range
For Each row In myRange.Rows
Dim cell As Range
For Each cell In row.Cells
If IsNumeric(cell.Value) Then
If cell.Value = Application.WorksheetFunction.Max(row) Then
cell.Interior.Color = RGB(253, 127, 127)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 2) Then
cell.Interior.Color = RGB(252, 181, 128)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 3) Then
cell.Interior.Color = RGB(253, 247, 127)
Else
cell.Interior.Color = RGB(199, 254, 126)
End If
End If
Next cell
Next row
End Sub
My Question: I am wondering, is it possible to run this VBA function directly in R?
我的问题是:我想知道是否可以直接在R中运行这个VBA函数?
I tried to follow the instructions here (https://stackoverflow.com/questions/19404270/run-vba-script-from-r):
我尝试按照这里的说明操作(https://stackoverflow.com/questions/19404270/run-vba-script-from-r):
library("devtools")
install_github('omegahat/RDCOMClient')
current_dir <- getwd()
file_path <- file.path(current_dir, "df.csv")
df <- read.csv(file_path)
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(file_path)
但是从这里开始,我不知道该怎么做。
但是从这里开始,我不知道该怎么做。
I am
英文:
I am working with the R programming language.
I have the following dataset:
df = structure(list(var1 = c(4.39524353447787, 7.6982251051672, 25.5870831414912,
10.7050839142458, 11.2928773516095, 27.1506498688328, 14.609162059892,
-2.65061234606534, 3.13147148106474, 5.54338029900042), var2 = c(22.2408179743946,
13.5981382705736, 14.0077145059405, 11.1068271594512, 4.44158865245925,
27.8691313680308, 14.9785047822924, -9.66617156629638, 17.0135590156369,
5.27208592272066), var3 = c(-0.678237059868451, 7.82025085341705,
-0.260044483072397, 2.7110877070886, 3.74960732150743, -6.86693310742413,
18.3778704449452, 11.5337311783652, -1.38136937011948, 22.5381492106993
), var4 = c(14.2646422147681, 7.04928517007729, 18.9512566104502,
18.7813348753304, 18.2158108163749, 16.8864025410009, 15.5391765353759,
9.38088289423278, 6.94037336260083, 6.19528998987617)), row.names = c(NA,
-10L), class = "data.frame")
write.csv(df, "df.csv")
Here is a VBA function I have that I am running from the VBA editor within Excel:
Sub ColorCellsRowWise()
Dim myRange As Range
Set myRange = Range("A2:D11")
Dim row As Range
For Each row In myRange.Rows
Dim cell As Range
For Each cell In row.Cells
If IsNumeric(cell.Value) Then
If cell.Value = Application.WorksheetFunction.Max(row) Then
cell.Interior.Color = RGB(253, 127, 127)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 2) Then
cell.Interior.Color = RGB(252, 181, 128)
ElseIf cell.Value = Application.WorksheetFunction.Large(row, 3) Then
cell.Interior.Color = RGB(253, 247, 127)
Else
cell.Interior.Color = RGB(199, 254, 126)
End If
End If
Next cell
Next row
End Sub
My Question: I am wondering, is it possible to run this VBA function directly in R?
I tried to follow the instructions here (https://stackoverflow.com/questions/19404270/run-vba-script-from-r):
library("devtools")
install_github('omegahat/RDCOMClient')
current_dir <- getwd()
file_path <- file.path(current_dir, "df.csv")
df <- read.csv(file_path)
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(file_path)
But from here I do not know what to do.
I am working on an R script where "df" is created in R, then saved as a CSV - and then I want to run the VBA script all in one shot. The approach in the above link seems like this might not be possible.
Can someone please show me how to do this?
Thanks!
答案1
得分: 3
以下是代码的中文翻译:
library(openxlsx)
wb <- createWorkbook()
addWorksheet(wb, "Sheet 1")
writeData(wb, 1, df)
rowranks <- t(apply(-df, 1, rank))
stylecolors <- c(
rgb(253, 127, 127, maxColorValue = 255),
rgb(252, 181, 128, maxColorValue = 255),
rgb(253, 247, 127, maxColorValue = 255),
rgb(199, 254, 126, maxColorValue = 255)
)
rowranks[] <- stylecolors[rowranks]
rowranks
# var1 var2 var3 var4
# [1,] "#FDF77F" "#FD7F7F" "#C7FE7E" "#FCB580"
# [2,] "#FDF77F" "#FD7F7F" "#FCB580" "#C7FE7E"
# [3,] "#FD7F7F" "#FDF77F" "#C7FE7E" "#FCB580"
# [4,] "#FDF77F" "#FCB580" "#C7FE7E" "#FD7F7F"
# [5,] "#FCB580" "#FDF77F" "#C7FE7E" "#FD7F7F"
# [6,] "#FCB580" "#FD7F7F" "#C7FE7E" "#FDF77F"
# [7,] "#C7FE7E" "#FDF77F" "#FD7F7F" "#FCB580"
# [8,] "#FDF77F" "#C7FE7E" "#FD7F7F" "#FCB580"
# [9,] "#FDF77F" "#FD7F7F" "#C7FE7E" "#FCB580"
# [10,] "#FDF77F" "#C7FE7E" "#FD7F7F" "#FCB580"
for (i in 1:nrow(df)) {
for (j in 1:ncol(df)) {
addStyle(wb, 1, style = createStyle(fgFill = rowranks[i, j]), rows = i+1, cols = j)
}
}
saveWorkbook(wb, "/tmp/quux.xlsx")
英文:
Perhaps you don't need VBA?
library(openxlsx)
wb <- createWorkbook()
addWorksheet(wb, "Sheet 1")
writeData(wb, 1, df)
rowranks <- t(apply(-df, 1, rank))
stylecolors <- c(
rgb(253, 127, 127, maxColorValue = 255),
rgb(252, 181, 128, maxColorValue = 255),
rgb(253, 247, 127, maxColorValue = 255),
rgb(199, 254, 126, maxColorValue = 255)
)
rowranks[] <- stylecolors[rowranks]
rowranks
# var1 var2 var3 var4
# [1,] "#FDF77F" "#FD7F7F" "#C7FE7E" "#FCB580"
# [2,] "#FDF77F" "#FD7F7F" "#FCB580" "#C7FE7E"
# [3,] "#FD7F7F" "#FDF77F" "#C7FE7E" "#FCB580"
# [4,] "#FDF77F" "#FCB580" "#C7FE7E" "#FD7F7F"
# [5,] "#FCB580" "#FDF77F" "#C7FE7E" "#FD7F7F"
# [6,] "#FCB580" "#FD7F7F" "#C7FE7E" "#FDF77F"
# [7,] "#C7FE7E" "#FDF77F" "#FD7F7F" "#FCB580"
# [8,] "#FDF77F" "#C7FE7E" "#FD7F7F" "#FCB580"
# [9,] "#FDF77F" "#FD7F7F" "#C7FE7E" "#FCB580"
# [10,] "#FDF77F" "#C7FE7E" "#FD7F7F" "#FCB580"
for (i in 1:nrow(df)) {
for (j in 1:ncol(df)) {
addStyle(wb, 1, style = createStyle(fgFill = rowranks[i, j]), rows = i+1, cols = j)
}
}
saveWorkbook(wb, "/tmp/quux.xlsx")
答案2
得分: 1
我会对你的架构进行一些调整,并通过 .bat
文件运行 R
脚本(假设你正在运行 Windows),并且还会通过 VBS
脚本运行工作簿中的 VBA
,这也由同一个 .bat
文件运行。这样,你可以按照你希望的顺序编排你的流程。这可能看起来有些繁琐,但这是一种相当标准的本地自动化任务方法。
英文:
I would change your architecture a little, and run the R
script from a .bat
file (assuming you are running windows) and also run the VBA
in your workbook via a VBS
script, which is also being run by the same .bat
file. In this way you can orchestrate your process in the order you desire. That might seem a bit cumbersome, but that's a fairly standard approach to on-prem automation tasks.
答案3
得分: 1
基本上,你需要将该 VBA 函数翻译成 R 和 RDCOMClient 调用。然而,你调用的一些方法是 VBA 函数(例如,RGB
),而另一些是 Excel 对象库的一部分(例如,Application.*
)。
由于 R 中的 for
循环不能像 VBA 的 For Each
那样迭代 Excel 对象,考虑使用整数迭代,这涉及使用 Cells
和 Range.Cells
属性。
最后,作为处理 COM 对象的最佳实践,始终清理后台进程,无论是否遇到错误,你都可以使用 R 的 tryCatch
处理。
library(RDCOMClient)
csvData <- file.path(getwd(), "df.csv", fsep="\\")
# ... 省略部分内容 ...
旁注:请注意,VBA 不是 Microsoft Excel 的一部分,而是一个外部组件(默认情况下连接到该软件)。它只是通过 COM 连接到 Excel 的对象库的另一种语言,大多数通用目的的编程语言(如 R)也可以这样连接。
英文:
Essentially, you need to translate that VBA function to R and RDCOMClient calls. However, some methods you call are VBA functions (e.g., RGB
) and others are part of the Excel object library (e.g., Application.*
).
Because R for
loops cannot iterate on Excel objects like VBA's For Each
, consider integer iteration which entails use of Cells
and Range.Cells
properties.
Finally, as best practice in dealing with COM objects, always clean out the background process whether you face an error or not which you can handle with R's tryCatch
.
library(RDCOMClient)
csvData <- file.path(getwd(), "df.csv", fsep="\\")
RGBtoINT <- function(R, G, B) (65536 * B + 256 * G + R)
tryCatch({
# INITIALIZE COM OBJECT
xlApp <- COMCreate("Excel.Application")
xlApp[["DisplayAlerts"]] <- FALSE
# CREATE WORKBOOK
xlWbk <- xlApp$Workbooks()$Add()
xlWks <- xlWbk$Worksheets(1)
xlWks[["Name"]] <- "DATAFRAME"
# IMPORT CSV DATA
xlQt <- xlWks$QueryTables()$Add(
Connection=paste0("TEXT;", csvData),
Destination=xlWks$Range("A1")
)
xlQt[["TextFileParseType"]] <- 1
xlQt[["TextFileCommaDelimiter"]] <- TRUE
xlQt$Refresh(BackgroundQuery=FALSE)
xlQt$Delete()
# ITERATE THROUGH ROWS AND CELLS
for(row in 1:11) {
rowRng <- xlWks$Range(xlWks$Cells(row, 1), xlWks$Cells(row, 4))
for(col in 1:4) {
cellRng <- xlWks$Cells(row, col)
cell_value <- cellRng$Value()
if(is.integer(cell_value) | is.numeric(cell_value)) {
if(cell_value == xlApp$WorksheetFunction()$Max(rowRng)) {
cellRng[["Interior"]][["Color"]] = RGBtoINT(253, 127, 127)
} else if(cell_value == xlApp$WorksheetFunction()$Large(rowRng, 2)) {
cellRng[["Interior"]][["Color"]] = RGBtoINT(252, 181, 128)
} else if(cell_value == xlApp$WorksheetFunction()$Large(rowRng, 3)) {
cellRng[["Interior"]][["Color"]] = RGBtoINT(253, 247, 127)
} else {
cellRng[["Interior"]][["Color"]] = RGBtoINT(199, 254, 126)
}
}
}
}
# SHOW BACKGROUND APP
xlApp[["Visible"]] <- TRUE
}, warning = identity
, error = function(e) {
identity(e)
# CLOSE OBJECTS
if(exists("xlQt")) xlQt$Delete()
if(exists("xlWbk")) xlWbk$Close(FALSE)
if(exists("xlApp")) xlApp$Quit()
}, finally = {
# RELEASE COM RESOURCES
rowRng <- NULL; cellRng <- NULL;
xlQt <- NULL; xlWks <- NULL; xlWbk <- NULL; xlApp <- NULL
rm(rowRng, cellRng, xlWks, xlWbk, xlApp)
})
Aside: Do note VBA is NOT part of Microsoft Excel but an external component (by default connected to the software). It is just another language to connect via COM to Excel's object library as most general purpose programming languages can such as R.
Input
df <- structure(list(var1 = c(4.39524353447787, 7.6982251051672, 25.5870831414912,
10.7050839142458, 11.2928773516095, 27.1506498688328, 14.609162059892,
-2.65061234606534, 3.13147148106474, 5.54338029900042), var2 = c(22.2408179743946,
13.5981382705736, 14.0077145059405, 11.1068271594512, 4.44158865245925,
27.8691313680308, 14.9785047822924, -9.66617156629638, 17.0135590156369,
5.27208592272066), var3 = c(-0.678237059868451, 7.82025085341705,
-0.260044483072397, 2.7110877070886, 3.74960732150743, -6.86693310742413,
18.3778704449452, 11.5337311783652, -1.38136937011948, 22.5381492106993
), var4 = c(14.2646422147681, 7.04928517007729, 18.9512566104502,
18.7813348753304, 18.2158108163749, 16.8864025410009, 15.5391765353759,
9.38088289423278, 6.94037336260083, 6.19528998987617)), row.names = c(NA,
-10L), class = "data.frame")
write.csv(df, "ColorFormatCell.csv", row.names=FALSE)
Output
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论