Запуск автономного макроса excel с пакетным файлом [duplicate]

Одно из лучших объяснений lambda expression дано автором C ++ Bjarne Stroustrup в его книге ***The C++ Programming Language*** глава 11 ( ISBN-13: 978-0321563842 ):

What is a lambda expression?

A лямбда-выражение , иногда также называемое функцией лямбда или (строго говоря, но разговорно) как лямбда , является упрощенным обозначением для определения и использования анонимного функционального объекта. Вместо определения именованного класса с помощью оператора (), позже создающего объект этого класса и, наконец, вызывающего его, мы можем использовать сокращенное обозначение.

When would I use one?

Это особенно полезно, когда мы хотим передать операцию в качестве аргумента алгоритму. В контексте графических пользовательских интерфейсов (и в других местах) такие операции часто называют обратными вызовами .

What class of problem do they solve that wasn't possible prior to their introduction?

Здесь Я предполагаю, что каждое действие, выполняемое с помощью лямбда-выражения, может быть разрешено без них, но с гораздо большим количеством кода и гораздо большей сложностью. Лямбда-выражение - это способ оптимизации вашего кода и способ сделать его более привлекательным. Как печально Stroustup:

эффективные способы оптимизации

Some examples

через lambda выражение

void print_modulo(const vector& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
{
    for_each(begin(v),end(v),
        [&os,m](int x) { 
           if (x%m==0) os << x << '\n';
         });
}

или через функцию

class Modulo_print {
         ostream& os; // members to hold the capture list int m;
     public:
         Modulo_print(ostream& s, int mm) :os(s), m(mm) {} 
         void operator()(int x) const
           { 
             if (x%m==0) os << x << '\n'; 
           }
};

или даже

void print_modulo(const vector& v, ostream& os, int m) 
     // output v[i] to os if v[i]%m==0
{
    class Modulo_print {
        ostream& os; // members to hold the capture list
        int m; 
        public:
           Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
           void operator()(int x) const
           { 
               if (x%m==0) os << x << '\n';
           }
     };
     for_each(begin(v),end(v),Modulo_print{os,m}); 
}

, если вам нужно u, можно назвать lambda expression, как показано ниже:

void print_modulo(const vector& v, ostream& os, int m)
    // output v[i] to os if v[i]%m==0
{
      auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
      for_each(begin(v),end(v),Modulo_print);
 }

Или предположим, что еще один простой образец

void TestFunctions::simpleLambda() {
    bool sensitive = true;
    std::vector v = std::vector({1,33,3,4,5,6,7});

    sort(v.begin(),v.end(),
         [sensitive](int x, int y) {
             printf("\n%i\n",  x < y);
             return sensitive ? x < y : abs(x) < abs(y);
         });


    printf("sorted");
    for_each(v.begin(), v.end(),
             [](int x) {
                 printf("x - %i;", x);
             }
             );
}

будет генерировать следующий

0

1

0

1

0

1

0

1

0

1

0 sortedx - 1; x - 3; x - 4; x - 5; x - 6; x - 7; x - 33;

[] - это список захвата или lambda introducer: если lambdas не требует доступа к своей локальной среде, мы можем его использовать.

Цитата из книги:

Первая Характер лямбда-выражения всегда [. Интенсификатор лямбда может принимать различные формы:

• []: пустой список захвата. Это означает, что никакие локальные имена из окружающего контекста не могут использоваться в лямбда-теле. Для таких лямбда-выражений данные получены из аргументов или из нелокальных переменных.

• [& amp;]: неявно захватывать по ссылке. Можно использовать все локальные имена. Доступ ко всем локальным переменным осуществляется по ссылке.

• [=]: неявно фиксировать по значению. Можно использовать все локальные имена. Все имена относятся к копиям локальных переменных, взятых в точке вызова лямбда-выражения.

• [capture-list]: явный захват; Список захвата - это список имен локальных переменных, которые должны быть захвачены (т. е. сохранены в объекте) по ссылке или по значению. Переменные с именами, которым предшествует & amp; записываются по ссылке. Другие переменные фиксируются по значению. Список захвата также может содержать это и имена, за которыми следуют ... как элементы.

• [& amp ;, capture-list]: неявно захватывать по ссылке все локальные переменные с именами, не указанными в списке. Этот список может содержать список захвата. Перечисленным именам не может предшествовать & amp ;. Переменные, названные в списке захвата, записываются по значению.

• [=, capture-list]: неявно захватывать по значению все локальные переменные с именами, не указанными в списке. Список захвата не может содержать этого. Перечисленным именам должно предшествовать & amp ;. Вариаторы, названные в списке захвата, записываются по ссылке.

Обратите внимание, что локальное имя, которому предшествует & amp; всегда фиксируется по ссылке и локальное имя, не указанное с помощью & amp; всегда фиксируется по значению.

Additional

Lambda expression format

Дополнительные ссылки:

58
задан STF 31 December 2015 в 14:47
поделиться

10 ответов

Вы можете запустить Excel, открыть книгу и запустить макрос из файла VBScript.

Скопировать код в блокнот.

Обновить ' MyWorkbook.xls 'и' MyMacro '.

Сохраните его с расширением vbs и запустите его.

Option Explicit

On Error Resume Next

ExcelMacroExample

Sub ExcelMacroExample() 

  Dim xlApp 
  Dim xlBook 

  Set xlApp = CreateObject("Excel.Application") 
  Set xlBook = xlApp.Workbooks.Open("C:\MyWorkbook.xls", 0, True) 
  xlApp.Run "MyMacro"
  xlApp.Quit 

  Set xlBook = Nothing 
  Set xlApp = Nothing 

End Sub 

Строка ключа, которая запускается макрос:

xlApp.Run «MyMacro»

70
ответ дан Robert Mearns 16 August 2018 в 01:21
поделиться
  • 1
    Это то, что я искал! Оно работает. Я должен добавить пару изменений, необходимых для этого, чтобы работать без сбоев: 1. Это «xlApp.Run». 2. Перед тем как уйти, нужно использовать xlApp.SaveAs или никакие изменения, сделанные макросом, не будут сохранены. (можно использовать xlApp.DisplayAlerts = False), чтобы избежать связанных всплывающих окон). 3. Перед тем, как выйти, вызывается xlApp.ActiveWorkbook.Close или электронная таблица остается открытой (хотя и скрытой), что отключает дальнейшее редактирование. В общем, это то, что я искал :) – Polymeron 24 January 2010 в 16:13
  • 2
    Также подумайте о добавлении xlApp.Visible = True, иначе вы не увидите Excel или любые его диалоговые окна, которые могут появиться. – Rachel Hettinger 14 October 2014 в 23:24
  • 3
    Процесс EXCEL.exe не закрывается, когда я запускаю этот скрипт дословно. – André Christoffer Andersen 27 October 2014 в 18:17
  • 4
    @Robert Mearns Я использовал этот VBS для запуска макроса в пакетном режиме (макрос работает в режиме интерактивного режима). Я запускаю этот VBS, но ответа не было вообще. Я подозреваю, что Set xlApp = CreateObject("Excel.Application") не работает в моей системе. Можете ли вы любезно посоветовать мне, как это сделать? – Mubeen Shahid 29 October 2014 в 10:34
  • 5
    Что из вашего файла excel защищено паролем, и вы хотите открыть его как чтение-запись? Что вы корректируете свой код? – Jason Samuels 5 August 2016 в 12:26

Вы можете проверить, открыт ли Excel. Нет необходимости создавать еще один isntance

   If CheckAppOpen("excel.application")  Then
           'MsgBox "App Loaded"
            Set xlApp = GetObject(, "excel.Application")   
   Else
            ' MsgBox "App Not Loaded"
            Set  wrdApp = CreateObject(,"excel.Application")   
   End If
1
ответ дан Adam Law 16 August 2018 в 01:21
поделиться

@ Robert: Я пытался адаптировать ваш код с относительным путем и создал командный файл для запуска VBS.

VBS запускается и закрывается, но не запускает макрос ... Любая идея о том, где проблема может быть?

Option Explicit

On Error Resume Next

ExcelMacroExample

Sub ExcelMacroExample() 

  Dim xlApp 
  Dim xlBook 

  Set xlApp = CreateObject("Excel.Application")
  Set objFSO = CreateObject("Scripting.FileSystemObject")
  strFilePath = objFSO.GetAbsolutePathName(".") 
  Set xlBook = xlApp.Workbooks.Open(strFilePath, "Excels\CLIENTES.xlsb") , 0, True) 
  xlApp.Run "open_form"


  Set xlBook = Nothing 
  Set xlApp = Nothing 

End Sub

Я удалил «Application.Quit», потому что мой макрос вызывает пользовательскую форму, заботясь об этом.

Cheers

EDIT

Я действительно сработал, на случай, если кто-то захочет запустить пользовательскую форму «как таковое»:

Проблемы, с которыми я столкнулся:

1 - Я не хотел использовать событие Workbook_Open, поскольку excel заблокирован только для чтения. 2 - Командная команда ограничена тем фактом, что (насколько мне известно) она не может вызвать макрос.

Сначала я написал макрос для запуска моей пользовательской формы при скрытии приложения:

Sub open_form()
 Application.Visible = False
 frmAddClient.Show vbModeless
End Sub

Затем я создал vbs для запуска этого макроса (выполнение этого с относительным путем было сложным):

dim fso
dim curDir
dim WinScriptHost
set fso = CreateObject("Scripting.FileSystemObject")
curDir = fso.GetAbsolutePathName(".")
set fso = nothing

Set xlObj = CreateObject("Excel.application")
xlObj.Workbooks.Open curDir & "\Excels\CLIENTES.xlsb"
xlObj.Run "open_form"

И я, наконец, сделал пакетный файл для выполнения VBS ...

@echo off
pushd %~dp0
cscript Add_Client.vbs

Обратите внимание, что я также включил «Установить обратно в видимый» в мой Userform_QueryClose:

Private Sub cmdClose_Click()
Unload Me
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    ThisWorkbook.Close SaveChanges:=True
    Application.Visible = True
    Application.Quit
End Sub

В любом случае, спасибо за вашу помощь, и я надеюсь, что это поможет если кому-то это нужно

2
ответ дан Axn40 16 August 2018 в 01:21
поделиться

Я всегда проверял количество открытых книг в Workbook_Open (). Если это 1, то рабочая книга была открыта командной строкой (или пользователь закрыл все книги, а затем открыл это).

If Workbooks.Count = 1 Then

    ' execute the macro or call another procedure - I always do the latter  
    PublishReport

    ThisWorkbook.Save

    Application.Quit

End If
2
ответ дан Brian Hoffman 16 August 2018 в 01:21
поделиться

Самый простой способ сделать это:

1) Запустить Excel из командного файла, чтобы открыть книгу, содержащую ваш макрос:

EXCEL.EXE /e "c:\YourWorkbook.xls"

2) Вызовите свой макрос из события Workbook_Open рабочей книги, например:

Private Sub Workbook_Open()
    Call MyMacro1          ' Call your macro
    ActiveWorkbook.Save    ' Save the current workbook, bypassing the prompt
    Application.Quit       ' Quit Excel
End Sub

Теперь это приведет к возврату элемента управления в пакетный файл для выполнения другой обработки.

16
ответ дан bvukas 16 August 2018 в 01:21
поделиться
  • 1
    Подумал об этом, но он будет работать, даже если я открою его не через пакетный файл, сделав сам файл невозможным без него, прежде чем отключать макросы. – Polymeron 13 January 2010 в 17:10
  • 2
    Это просто решить, изменив параметр реестра, который сообщает Excel, какой уровень безопасности установлен. – bvukas 18 January 2010 в 23:11
  • 3
    Конечно, цифровое подписание книги всегда помогает, даже с сертификатом тестирования :) – bvukas 19 January 2010 в 16:42
  • 4
    И все равно делать это без Excel ?. Я имею в виду, что другая программа более специализирована для быстрого выполнения макросов из командной строки. – skan 16 October 2013 в 23:54
  • 5
    Как я могу открыть файл без запуска макроса, если мне нужно что-то изменить? – wviana 18 July 2016 в 18:06

Если вы более комфортно работаете внутри Excel / VBA, используйте событие open и проверяйте среду: либо есть файл сигнала, запись реестра или переменная среды, которая контролирует то, что делает открытое событие.

Вы можете создать файл / настройку снаружи и протестировать внутри (используйте GetEnviromentVariable для env-vars) и легко протестируйте. Я написал VBScript, но сходство с VBA вызывает у меня больше ярости, чем легкость.

[подробнее]

Насколько я понимаю, вы хотите использовать таблицу обычно чаще всего / Некоторое время все же он запускается в пакетном режиме и делает что-то дополнительное / другое. Вы можете открыть лист из командной строки excel.exe, но вы не можете контролировать, что он делает, если он не знает, где он находится. Использование переменной среды относительно просто и упрощает тестирование электронной таблицы.

Чтобы уточнить, используйте приведенную ниже функцию для изучения среды. В модуле declare:

Private Declare Function GetEnvVar Lib "kernel32" Alias "GetEnvironmentVariableA" _
    (ByVal lpName As String, ByVal lpBuffer As String, ByVal nSize As Long) As Long

Function GetEnvironmentVariable(var As String) As String
Dim numChars As Long

    GetEnvironmentVariable = String(255, " ")

    numChars = GetEnvVar(var, GetEnvironmentVariable, 255)

End Function

В открывшемся событии Workbook (как и другие):

Private Sub Workbook_Open()
    If GetEnvironmentVariable("InBatch") = "TRUE" Then
        Debug.Print "Batch"
    Else
        Debug.Print "Normal"
    End If
End Sub

Добавить активный код, если применимо. В пакетном файле используйте

set InBatch=TRUE
2
ответ дан Chris Chambers 16 August 2018 в 01:21
поделиться

вы можете написать vbscript, чтобы создать экземпляр excel с помощью метода createobject (), затем откройте книгу и запустите макрос. Вы можете либо напрямую вызвать vbscript, либо вызвать vbscript из командного файла.

Вот ресурс, который я только что наткнулся: http://www.codeguru.com/forum/showthread. PHP? т = 376401

4
ответ дан Fink 16 August 2018 в 01:21
поделиться

Вместо прямого сравнения строк (VB не найдет их равными, так как GetEnvironmentVariable возвращает строку длиной 255), напишите это:

Private Sub Workbook_Open()     
    If InStr(1, GetEnvironmentVariable("InBatch"), "TRUE", vbTextCompare) Then
        Debug.Print "Batch"  
        Call Macro
    Else    
        Debug.Print "Normal"     
    End If 

End Sub 
2
ответ дан laybmw 16 August 2018 в 01:21
поделиться

Метод, показанный ниже, позволяет запускать определенный макрос Excel из командного файла, он использует переменную окружения для передачи имени макроса из пакета в Excel.

Поместите этот код в командный файл (используйте ваши пути к EXCEL.EXE и к книге):

Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"

Поместите этот код в Excel VBA ThisWorkBook Object:

Private Sub Workbook_Open()
    Dim strMacroName As String
    strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
    If strMacroName <> "" Then Run strMacroName
End Sub

И поместите свой код в модуль Excel VBA, как показано ниже:

Sub MyMacro()
    MsgBox "MyMacro is running..."
End Sub

Запустить командный файл и получить результат:

В случае, если вы не собираетесь запустите любой макрос, просто поместите пустые значения Set MacroName= в пакет.

3
ответ дан omegastripes 16 August 2018 в 01:21
поделиться

Я частично отношусь к C #. Я использовал следующие linqpad. Но это можно было легко скомпилировать с помощью csc и запустить вызов из командной строки.

Не забудьте добавить пакеты excel в пространство имен.

void Main()
{
    var oExcelApp = (Microsoft.Office.Interop.Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
    try{
        var WB = oExcelApp.ActiveWorkbook;
        var WS = (Worksheet)WB.ActiveSheet;
        ((string)((Range)WS.Cells[1,1]).Value).Dump("Cell Value"); //cel A1 val
        oExcelApp.Run("test_macro_name").Dump("macro");
    }
    finally{
        if(oExcelApp != null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcelApp);
        oExcelApp = null;
    }
}
0
ответ дан t3dodson 16 August 2018 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: