我正在尝试编写VBA解析器; 为了创建一个ConstantNode
,我需要能够匹配Const
声明的所有可能变体.
这些工作很漂亮:
Const foo = 123
Const foo$ = "123"
Const foo As String = "123"
Private Const foo = 123
Public Const foo As Integer = 123
Global Const foo% = 123
但我有两个问题:
如果在声明的末尾有评论,我会把它作为价值的一部分:
Const foo = 123 'this comment is included as part of the value
Run Code Online (Sandbox Code Playgroud)如果在同一条指令中声明了两个或多个常量,我将无法匹配整个指令:
Const foo = 123, bar = 456
Run Code Online (Sandbox Code Playgroud)这是我正在使用的正则表达式:
/// <summary>
/// Gets a regular expression pattern for matching a constant declaration.
/// </summary>
/// <remarks>
/// …
Run Code Online (Sandbox Code Playgroud) 我有一个.g4语法用于vba/vb6一个词法分析器/解析器,其中词法分析器正在跳过行连续标记 - 不跳过它们会破坏解析器而不是一个选项.这是有问题的词法分析器规则:
LINE_CONTINUATION : ' ' '_' '\r'? '\n' -> skip;
Run Code Online (Sandbox Code Playgroud)
这导致的问题是,只要从第1列开始继续行,解析器就会爆炸:
Run Code Online (Sandbox Code Playgroud)Sub Test() Debug.Print "Some text " & _ vbNewLine & "Some more text" End Sub
我想"嘿,我知道!我只是预处理字符串我正在喂ANTLR在下划线之前插入一个额外的空格,并改变语法接受它!"
所以我改变了这样的规则:
LINE_CONTINUATION : WS? WS '_' NEWLINE -> skip;
NEWLINE : WS? ('\r'? '\n') WS?;
WS : [ \t]+;
Run Code Online (Sandbox Code Playgroud)
... 上面的测试vba代码给了我这个解析器错误:
无关的输入'vbNewLine'期待WS
目前我唯一的解决方案是告诉我的用户正确缩进他们的代码.有什么方法可以解决这个语法规则吗?
我已经实现了一个基本的(天真的?)LINQ提供程序,它可以用于我的目的,但是我想解决一些怪癖,但我不确定如何.例如:
// performing projection with Linq-to-Objects, since Linq-to-Sage won't handle this:
var vendorCodes = context.Vendors.ToList().Select(e => e.Key);
Run Code Online (Sandbox Code Playgroud)
我的IQueryProvider
实现有一个CreateQuery<TResult>
看起来像这样的实现:
public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
{
return (IQueryable<TResult>)Activator
.CreateInstance(typeof(ViewSet<>)
.MakeGenericType(elementType), _view, this, expression, _context);
}
Run Code Online (Sandbox Code Playgroud)
显然,当Expression
a是a MethodCallExpression
并且TResult
是a时string
,这会产生窒息,所以我想我会执行这个糟糕的事情:
public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
{
var elementType = TypeSystem.GetElementType(expression.Type);
if (elementType == typeof(EntityBase))
{
Debug.Assert(elementType == typeof(TResult));
return (IQueryable<TResult>)Activator.CreateInstance(typeof(ViewSet<>).MakeGenericType(elementType), _view, this, expression, _context);
}
var methodCallExpression = expression as MethodCallExpression;
if(methodCallExpression != null …
Run Code Online (Sandbox Code Playgroud) 我有一个问题,我的COM加载项拖了几个月,我无法弄清楚为什么.
该IDTExtensibility2
实施已经由Carlos Quintero(MZ-Tools背后的人)进行了同行评审,并且被认为是正确的.
根据他的建议,OnBeginShutdown
实现设置了一个签入的标志OnDisconnection
,以确保ShutdownAddIn
只运行一次(某些VBE主机应用程序不调用OnBeginShutdown
,这就是原因):
public void OnBeginShutdown(ref Array custom)
{
_isBeginShutdownExecuted = true;
ShutdownAddIn();
}
Run Code Online (Sandbox Code Playgroud)
我的插件使用Ninject进行DI/IoC,我的ShutdownAddIn
方法归结为调用Dispose
Ninject IKernel
实例,然后释放所有COM对象Marshal.ReleaseComObject
:
private void ShutdownAddIn()
{
if (_kernel != null)
{
_kernel.Dispose();
_kernel = null;
}
_ide.Release();
_isInitialized = false;
}
Run Code Online (Sandbox Code Playgroud)
我想不出更早的时间来运行这段代码.然而,当Dispose
我的命令栏和菜单包装奔跑,我发现了一个InvalidCastException
在StopEvents
当命令栏/菜单尝试拆卸他们的控制:
public void HandleEvents()
{
// register the unmanaged click events
((Microsoft.Office.Core.CommandBarButton)Target).Click += Target_Click;
}
public void StopEvents()
{
// unregister …
Run Code Online (Sandbox Code Playgroud) 我在GitHub上有一个OSS项目是在AppVeyor CI上用Visual Studio 2017构建的.NET 4.5(不是预览的东西,只是2017).
该解决方案构建了一个COM加载项,扩展了一个着名的可怕的传统Win32 IDE,我们已经确定我们需要运行的最早的Windows版本是Vista(所以,.net 4.5及其async/await
非常棒).
到现在为止还挺好.现在构建一个COM可见的.net DLL是一回事,构建一个在进程中运行的COM加载项,托管在20年前最后一次更新的繁琐应用程序中,是另一个:我们不能依赖.net垃圾收集清理RCW是不确定的,因此很容易意外地泄漏COM对象并引入严重的运行时(实际拆除)问题,因此核心贡献者之一是将一个Roslyn分析器项目添加到解决方案中,这将有助于贡献者新旧通过防止可能引入这种泄漏的构建.
所以解决方案中的所有.csproj文件都得到了这个差异:
+ <ItemGroup>
+ <Analyzer Include="..\RubberduckCodeAnalysis\RubberduckCodeAnalysis\bin\Release\netstandard1.3\RubberduckCodeAnalysis.dll" />
+ </ItemGroup>
Run Code Online (Sandbox Code Playgroud)
因此,需要首先构建分析器项目.
有.sln diff显示新分析器项目的GUID:
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RubberduckCodeAnalysis", "RubberduckCodeAnalysis\RubberduckCodeAnalysis\RubberduckCodeAnalysis.csproj", "{A2B4E037-A446-41B9-A304-F91C7C7A6972}"
+EndProject
Run Code Online (Sandbox Code Playgroud)
然后.sln diff显示解决方案的一个项目以及如何将分析器添加为依赖项以控制构建顺序:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.Parsing", "Rubberduck.Parsing\Rubberduck.Parsing.csproj", "{A4A618E1-CBCA-435F-9C6C-5181E030ADFC}"
ProjectSection(ProjectDependencies) = postProject
+ {A2B4E037-A446-41B9-A304-F91C7C7A6972} = {A2B4E037-A446-41B9-A304-F91C7C7A6972}
{8CE35EB3-8852-4BA1-84DD-DF3F5D2967B0} = {8CE35EB3-8852-4BA1-84DD-DF3F5D2967B0}
EndProjectSection
EndProject
Run Code Online (Sandbox Code Playgroud)
这让我想到AppVeyor构建错误,我被困在:
C:\ Program Files(x86)\ Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1603,5):错误:项目'C:\ projects\rubberduck\RubberduckCodeAnalysis\RubberduckCodeAnalysis\RubberduckCodeAnalysis.csproj'目标'netstandard1.3'.它不能被针对".NETFramework,Version = v4.5"的项目引用.[C:\项目\ rubberduck\Rubberduck.Parsing\Rubberduck.Parsing.csproj]
在本地调试版本中,可以手动构建分析器项目,然后可以很好地构建和分析解决方案的其余部分,而无需破解项目依赖性.
在AppVeyor CI构建服务器上,分析器项目只是一个DLL,它是解决方案的一部分,如果我们不告诉它首先构建,那么将找不到分析器DLL并且解决方案将无法构建.
看起来我卡住了,无论我看哪个问题.我的用户都是Win32用户,我不关心可移植性; 我确实喜欢在Windows Vista上运行,所以有没有办法在没有将项目重新定位到.NET Standard 1.3的情况下构建CI?
我有一个插件和一个工作簿打开.插件是.xlam文件,在工作簿中我添加了对它的引用.插件受密码保护.
可以从我的工作簿中运行addin的公共方法.然而,在一个插件的方法使用的VBA.UserForms.Add
打开是在运行时创建的窗体像这样
让我们说一个引用的工作簿myAddin
有这个:
Private Sub callAddin()
myAddin.ShowForm ThisWorkbook
End Sub
Run Code Online (Sandbox Code Playgroud)
通常,我的插件中的代码如下所示:
Public Sub ShowForm(CallerWorkbook As Workbook)
Const vbext_ct_MSForm As Long = 3
'This is to stop screen flashing while creating form
Application.VBE.MainWindow.Visible = False
'Add to ThisWorkbook, not supplied workbook or VBE will crash - ignore CallerWorkbook
Dim myForm As Object
Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
'Create the User Form
With myForm
.Properties("Caption") = "Select"
.Properties("Width") = 300
.Properties("Height") = 270
End With
'Show the form …
Run Code Online (Sandbox Code Playgroud) 需要将所有工作表导出到一个 PDF 文件中,所以我找到了这段代码,它可以工作(导出单个 PDF,每张工作表都有一个页面)。但我不想使用 select / active 语句,我更喜欢使用存储对象的变量。
问题:如何避免在这段代码中选择/ ActiveSheet?
ThisWorkbook.Sheets(Array("Sheet1", "Sheet2")).Select
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"C:\tempo.pdf", Quality:= xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=True
Run Code Online (Sandbox Code Playgroud) 我有一个IEnumerable<Entityclass>
有一个string
和一个int
成员的实体.我需要将其转换为数组,KeyValuePair<string, double>
反之亦然.
它失败并出现强制转换错误.
[DataContract]
public class Entityclass
{
[DataMember]
public string text{ get; set; }
[DataMember]
public int textcount{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我有 IEnumerable<Entityclass>
我如何转换IEnumerable<Entityclass>
为数组KeyvaluePair<string,
double>[]
?
如何将KeyvaluePair<string, double>[]
数组转换为KeyvaluePair<string, int>[]
数组?
如何转换KeyvaluePair<string, double>
回IEnumerable?
我试过了:
topics is IEnumerable<Entityclass>;
topics.Cast<KeyValuePair<string, double>>().ToArray();
失败并出现施法错误我正在尝试找到我的代码崩溃的行号,但是这个网站上的许多解释似乎对我的级别来说很复杂.
我的代码基本上如下,我不知道它在哪里打破.
Sub1
Call function1
Call function2
End Sub
Run Code Online (Sandbox Code Playgroud)
该网站上的其他答案似乎只是一个简短的功能.但我不知道在我的代码中调用函数的位置或者如何获取弹出消息.如果我打算将我的sub1代码放入他们的函数中,我也不知道在哪里.初学者在这里.
在最长的时间里,我想IsNumeric("1.23E45")
回归True
是因为"E"代表科学记数法,使1.23E45为1.23x10 45.
最近我注意到IsNumeric("1.23D34")
也回来了True
,我为什么难过.
双方D
并E
产生相同的结果:
?val("1.23d45")
1.23E+45
?val("1.23e45")
1.23E+45
Run Code Online (Sandbox Code Playgroud)
怎么会?