Одно из лучших объяснений 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Дополнительные ссылки:
- Wiki
- open-std.org , глава 5.1.2
Вы можете запустить 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»
Вы можете проверить, открыт ли 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
@ 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
В любом случае, спасибо за вашу помощь, и я надеюсь, что это поможет если кому-то это нужно
Я всегда проверял количество открытых книг в 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
Самый простой способ сделать это:
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
Теперь это приведет к возврату элемента управления в пакетный файл для выполнения другой обработки.
Если вы более комфортно работаете внутри 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
вы можете написать vbscript, чтобы создать экземпляр excel с помощью метода createobject (), затем откройте книгу и запустите макрос. Вы можете либо напрямую вызвать vbscript, либо вызвать vbscript из командного файла.
Вот ресурс, который я только что наткнулся: http://www.codeguru.com/forum/showthread. PHP? т = 376401
Вместо прямого сравнения строк (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
Метод, показанный ниже, позволяет запускать определенный макрос 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=
в пакет.
Я частично отношусь к 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;
}
}
xlApp.Visible = True
, иначе вы не увидите Excel или любые его диалоговые окна, которые могут появиться. – Rachel Hettinger 14 October 2014 в 23:24EXCEL.exe
не закрывается, когда я запускаю этот скрипт дословно. – André Christoffer Andersen 27 October 2014 в 18:17Set xlApp = CreateObject("Excel.Application")
не работает в моей системе. Можете ли вы любезно посоветовать мне, как это сделать? – Mubeen Shahid 29 October 2014 в 10:34