R: 在R中运行VBA函数

huangapple go评论96阅读模式
英文:

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 = &quot;data.frame&quot;)

write.csv(df, &quot;df.csv&quot;)

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(&quot;A2:D11&quot;)

    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(&quot;devtools&quot;)
install_github(&#39;omegahat/RDCOMClient&#39;)


current_dir &lt;- getwd()
file_path &lt;- file.path(current_dir, &quot;df.csv&quot;)
df &lt;- read.csv(file_path)

xlApp &lt;- COMCreate(&quot;Excel.Application&quot;)
xlWbk &lt;- 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")

R: 在R中运行VBA函数

英文:

Perhaps you don't need VBA?

library(openxlsx)

wb &lt;- createWorkbook()
addWorksheet(wb, &quot;Sheet 1&quot;)
writeData(wb, 1, df)

rowranks &lt;- t(apply(-df, 1, rank))
stylecolors &lt;- 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[] &lt;- stylecolors[rowranks]
rowranks
#       var1      var2      var3      var4     
#  [1,] &quot;#FDF77F&quot; &quot;#FD7F7F&quot; &quot;#C7FE7E&quot; &quot;#FCB580&quot;
#  [2,] &quot;#FDF77F&quot; &quot;#FD7F7F&quot; &quot;#FCB580&quot; &quot;#C7FE7E&quot;
#  [3,] &quot;#FD7F7F&quot; &quot;#FDF77F&quot; &quot;#C7FE7E&quot; &quot;#FCB580&quot;
#  [4,] &quot;#FDF77F&quot; &quot;#FCB580&quot; &quot;#C7FE7E&quot; &quot;#FD7F7F&quot;
#  [5,] &quot;#FCB580&quot; &quot;#FDF77F&quot; &quot;#C7FE7E&quot; &quot;#FD7F7F&quot;
#  [6,] &quot;#FCB580&quot; &quot;#FD7F7F&quot; &quot;#C7FE7E&quot; &quot;#FDF77F&quot;
#  [7,] &quot;#C7FE7E&quot; &quot;#FDF77F&quot; &quot;#FD7F7F&quot; &quot;#FCB580&quot;
#  [8,] &quot;#FDF77F&quot; &quot;#C7FE7E&quot; &quot;#FD7F7F&quot; &quot;#FCB580&quot;
#  [9,] &quot;#FDF77F&quot; &quot;#FD7F7F&quot; &quot;#C7FE7E&quot; &quot;#FCB580&quot;
# [10,] &quot;#FDF77F&quot; &quot;#C7FE7E&quot; &quot;#FD7F7F&quot; &quot;#FCB580&quot;

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, &quot;/tmp/quux.xlsx&quot;)

R: 在R中运行VBA函数

答案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 对象,考虑使用整数迭代,这涉及使用 CellsRange.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 &lt;- file.path(getwd(), &quot;df.csv&quot;, fsep=&quot;\\&quot;)
RGBtoINT &lt;- function(R, G, B) (65536 * B + 256 * G + R)

tryCatch({
    # INITIALIZE COM OBJECT
    xlApp &lt;- COMCreate(&quot;Excel.Application&quot;)
    xlApp[[&quot;DisplayAlerts&quot;]] &lt;- FALSE

    # CREATE WORKBOOK
    xlWbk &lt;- xlApp$Workbooks()$Add()

    xlWks &lt;- xlWbk$Worksheets(1)
    xlWks[[&quot;Name&quot;]] &lt;- &quot;DATAFRAME&quot;

    # IMPORT CSV DATA
    xlQt &lt;- xlWks$QueryTables()$Add(
      Connection=paste0(&quot;TEXT;&quot;, csvData),
      Destination=xlWks$Range(&quot;A1&quot;)
    )
    xlQt[[&quot;TextFileParseType&quot;]] &lt;- 1
    xlQt[[&quot;TextFileCommaDelimiter&quot;]] &lt;- TRUE
    xlQt$Refresh(BackgroundQuery=FALSE)
    xlQt$Delete()

    # ITERATE THROUGH ROWS AND CELLS
    for(row in 1:11) {
        rowRng &lt;- xlWks$Range(xlWks$Cells(row, 1), xlWks$Cells(row, 4))

        for(col in 1:4) {
            cellRng &lt;- xlWks$Cells(row, col)
            cell_value &lt;- cellRng$Value()

            if(is.integer(cell_value) | is.numeric(cell_value)) {
                if(cell_value == xlApp$WorksheetFunction()$Max(rowRng)) {
                    cellRng[[&quot;Interior&quot;]][[&quot;Color&quot;]] = RGBtoINT(253, 127, 127)
                } else if(cell_value == xlApp$WorksheetFunction()$Large(rowRng, 2)) {
                    cellRng[[&quot;Interior&quot;]][[&quot;Color&quot;]] = RGBtoINT(252, 181, 128)
                } else if(cell_value == xlApp$WorksheetFunction()$Large(rowRng, 3)) {
                    cellRng[[&quot;Interior&quot;]][[&quot;Color&quot;]] = RGBtoINT(253, 247, 127)
                } else {
                    cellRng[[&quot;Interior&quot;]][[&quot;Color&quot;]] = RGBtoINT(199, 254, 126)
                }
            }
        }
    }

    # SHOW BACKGROUND APP
    xlApp[[&quot;Visible&quot;]] &lt;- TRUE

}, warning = identity

, error = function(e) {
    identity(e)
    
    # CLOSE OBJECTS
    if(exists(&quot;xlQt&quot;)) xlQt$Delete()
    if(exists(&quot;xlWbk&quot;)) xlWbk$Close(FALSE)
    if(exists(&quot;xlApp&quot;)) xlApp$Quit()

}, finally = {
    # RELEASE COM RESOURCES
    rowRng &lt;- NULL; cellRng &lt;- NULL; 
    xlQt &lt;- NULL; xlWks &lt;- NULL; xlWbk &lt;- NULL; xlApp &lt;- 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 &lt;- 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 = &quot;data.frame&quot;)

write.csv(df, &quot;ColorFormatCell.csv&quot;, row.names=FALSE)

Output

R: 在R中运行VBA函数

huangapple
  • 本文由 发表于 2023年6月5日 05:06:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402413.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定