好的,我正在为一个遗留的Excel-VBA应用程序完成一个附加项目,我再一次遇到了神秘范围的难题.Rows(?)和worksheet.Rows属性.
有谁知道这些属性真正做了什么以及它们应该为我提供什么?(注意:所有这些可能也适用于相应的*.Columns属性).
我真的希望能够使用它是返回一系列行,如下所示:
SET rng = wks.Rows(iStartRow, iEndRow)
Run Code Online (Sandbox Code Playgroud)
但是我从来没有能够做到这一点,即使Intellisense为它显示了两个参数.相反,我必须使用其他两种(非常kludgy)技术中的一种.
帮助是非常无益的(对于Office VBA通常如此),并且对于"Rows"的Google搜索并不是非常有用,无论我添加了多少其他术语.
我能够使用它的唯一的事情是1)返回单行作为范围(rng.Rows(i))和2)返回范围(rng.Rows.Count)中的行的计数.是吗?真的没有别的东西吗?
澄清:我知道它会返回一个范围,并且还有其他方法可以获得一系列行.我要求的具体是我们从.Cells()和.Range()得到的.Rows()得到了什么?我知道的两件事是1)返回单行范围的简单方法和2)计算范围内行数的方法.
还有别的事吗?
我正在使用C#和Microsoft.Office.Interop阅读Excel工作表数据.工作表包含一些日期值.当我试图读取该值时,它只是给出了数字(可能是TimeSpan).我在将此数字转换为DateTime时遇到问题.
以下是代码:
TimeSpan ts = TimeSpan.Parse(((Range)ws.Cells[4, 1]).Value2.ToString());
Run Code Online (Sandbox Code Playgroud)
哪里ws
是Excel.WorkSheet
.
任何人都可以解释我应该如何将这个数字(TimeSpan
)转换成DateTime
?
感谢您分享宝贵的时间.
我有一个小应用程序,它通过COM/OLE自动化自动化Microsoft Word.
不幸的是,这不适用于Word的虚拟化即点即用版本,因为它们在注册表中没有所需的密钥.(至少不是它们被删除的地方)换句话说:CreateObject
失败,因为没有注册必要的COM类.
有没有办法自动化即点即用版的Microsoft Office?也许是一些兼容层?
编辑:我发现只有两页用户/开发人员抱怨这个.OLE自动化已经过时或者没有人使用C2R版本......
我正在将DateTime转换为OADate.我希望在将OADate转换回时获得完全相同的DateTime,但现在它只有毫秒级的分辨率,因此不同.
var a = DateTime.UtcNow;
double oadate = a.ToOADate();
var b = DateTime.FromOADate(oadate);
int compare = DateTime.Compare(a, b);
//Compare is not 0; the date times are not the same
Run Code Online (Sandbox Code Playgroud)
来自a:634202170964319073
来自b的筹码:634202170964310000
OADate双倍:40437.290467951389
这是什么原因?DateTime的分辨率显然足够好.
是否可以在Java中使用OLE自动化?如果没有,为什么在Java中不可能?
我希望自动导出不同格式的excel电子表格(即.csv等...)
在此先感谢您的答案:)
解释我的确切情况有点困难,但我会尝试:
我正在检查通过后期绑定创建的DOM接口,并在某个时候选择一个返回接口OleVariant元素的范围(我知道这肯定).
我期待一个,IHTMLElement2
但它不是(我得到一个例外,该对象没有tagName
属性).这让我后来怀疑(尚未测试)它的Node元素(具有nodeName
属性) - 但我不想猜,并问:
if Supports(IDispatch(v), IWhatEver1)... else if Supports(IDispatch(v), IWhatEver2)...
我不知道它支持哪个界面.我怎么知道OleVariant接口对象的接口名称/ guid?
问题不仅仅是特定于DOM,例如,我有一个OleVariant是通过以下方式创建的:
SomeObject := CreateOleObject('WinHttp.WinHttpRequest.5.1');
or
SomeObject := CreateOleObject('Msxml.ServerXMLHTTP');
or
SomeObject := CreateOleObject('Msxml.XMLHTTP');
etc...
v := SomeObject;
Run Code Online (Sandbox Code Playgroud)
我以后如何知道哪个IDispatch落后v
?
我希望这个问题很清楚.
似乎IE11在使用FEATURE_BROWSER_EMULATION = 8000
我的应用程序时改变了它的行为- >当你在设计模式下使用TWebBrowser并选择一个范围vElement
(所选范围中的元素)返回为JScriptTypeInfo
...我不知道为什么,我不知道还是如何处理这个bs,但至少我知道我有哪个界面!
这是我用来检查元素的代码:
if SysUtils.Supports(IUnknown(vElement), IDispatch, LDispatch) then
begin
debug('vElement Supports IDispatch');
if LDispatch.GetTypeInfo(0, 0, ti) = S_OK then
if ti.GetDocumentation(MEMBERID_NIL, @pbstrName, @pbstrDocString, nil, nil) = S_OK then …
Run Code Online (Sandbox Code Playgroud) 下面是我尝试IAdviseSink
在我的TForm1
类中设置接口以捕获新创建的MSWord文档的一些事件的代码.代码运行时我没有任何错误,但我无法捕获任何事件,同时保存文档或关闭它.如何IAdviseSink
正确设置MSWord文档?
var
Form1 : TForm1;
doc_ole_obj : IOleObject;
word : IDispatch;
Connection: LongInt;
implementation
//------------ Setup IAdviseSink
procedure TForm1.Setup;
begin
word := CreateOleObject('Word.Application');
OleVariant(word).Visible := True;
IUnknown(OleVariant(word).Documents.Open('file.doc')).QueryInterface(IOleObject,doc_ole_obj);
doc_ole_obj.Advise(IAdviseSink(Self), Connection);
end;
//------------- catch Sink events
procedure TForm1.OnSave;
begin
Caption := 'saved at ' + TimeToStr(Now);
end;
我有一个小方法,试图枚举Word文档中的字段.很长一段时间以来,我不得不做这种事情,现在我不记得如何正确地做到这一点.
下面的代码是使用OleVariants,我已经尝试了一段时间,谷歌搜索没有提出德尔福解决方案.任何人都可以建议如何解决这个问题?
代码的最终目标是识别特定类型的字段并使用该信息来删除所述字段.
procedure TForm2.Button1Click(Sender: TObject);
var
I: Integer;
begin
If OpenDialog1.Execute Then
Begin
WordApp := CreateOLEObject( 'Word.Application' );
WordDocument := WordApp.Documents.Open( OpenDialog1.FileName, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam, EmptyParam,
EmptyParam );
for I := 0 to WordDocument.Fields.Count - 1 do
begin
ShowMessage( WordDocument.Fields[ I ].Code );
end;
End;
end;
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我知道这段代码让Word打开了所有这些.
这暂时还不错,我现在主要担心的是让事情发挥作用.
我也尝试将循环更改为:
for I := 0 to WordDocument.Fields.Count -1 do
begin
ShowMessage( WordDocument.Fields.Item( I ).Code );
end;
Run Code Online (Sandbox Code Playgroud)
但没有奏效,告诉我"物品"不是收藏品的一部分.
我已经没想完了.
在为某个对象类型声明了一个数组(其中该类型不使用从COM的接口派生的接口(&因此未正确设置以启用[OLE] Automation的后期绑定技术))后,尝试根据我的期望将数组分配给变量不起作用。IDispatch
Variant
具体而言,似乎发生的情况是将指向数组的积分指针分配给了Variant
变量,而不是数组的副本。
谁能解释这种行为?这是VBA 7.1语言的标准行为吗?[EDIT-A1]是VBA的Variant
类型不能处理此类数组吗?[EDIT-A2]
[EDIT-A1]- 当前(19年4月6日),看起来像是个错误。
[EDIT-A2]- 否,因为ByRef
Variant
如果将这样的数组作为此类参数的值传递,则参数的内部过程参数可以正确指向此类数组。
有关正在发生的事情的更多详细信息
在检查了各种内存地址和指针之后,似乎正在发生的事情是,在将此类数组分配给Variant
变量时,实际上是分配了指向数组“ VB安全数组指针”的Long
(或LongPtr
)指针。这与VBA语言规范中此处记录的预期的行为相反。在查看有关VB数组及其内存布局的VB6文档(存储在此处)之后,我推断出发生了这种指针分配。
我对问题是否先前已被记录的研究
我搜索了Internet,Office VBA参考文档和VBA语言规范,以查看是否有人记录了此问题。我发现该问题可能已被部分记录的唯一地方是在此处发布的堆栈溢出答案中。不幸的是,该帖子没有对这个问题说太多。
我测试过的特定数组类型
我曾经历过与使用接口不下列对象类型的数组这个问题获得来自IDispatch
:
stdole.IUnknown
*stdole.IFont
mscoree.CorRuntimeHost
†mscorlib.AppDomain
†mscorlib.Type
*来自的OLE Automation COM类型库stdole2.tlb
。
†来自.NET Framework v4.0.30319的COM类型库。
关于使用不源自的接口的对象类型的更多信息 …
我有以下VBScript脚本,它创建一个Microsoft COM对象.
set foo = CreateObject("Bar.ProgId")
foo.Einfügen()
Run Code Online (Sandbox Code Playgroud)
该COM对象的实现位于动态链接库中Foo.dll
,该库使用Microsoft Foundation Framework(MFC),尤其是Dispatch Maps的机制.
Dispatch Maps显示如下
BEGIN_DISPATCH_MAP(Foo, CCmdTarget)
[...]
DISP_FUNCTION(Foo, "Einfügen", Insert, VT_I2, VTS_NONE)
[...]
END_DISPATCH_MAP()
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.当我在VBA环境中创建这样的COM对象时,例如在Excel应用程序中,调用foo.Einfügen
成功.除了在VBScript-Script中.
我认识到OLE自动化应用于VBA以及VBScript.但是当我运行VBScript-Script时,我收到了错误
错误:未知字符; 代码8000A0408;
来源:在Microsoft VBScript中编译失败
首先我认为VBScript-Script中的编码因为字符ü
而错误,但我确认它是ANSI编码的.我还验证了我系统上的Windows代码页是Windows-1252西方拉丁字符集.
如果我在Dispatch Map中更改Einfügen
为Einfuegen
I断言VBScript-Script正在运行.
所以我的问题是,为什么foo.Einfügen
VBScript 中的调用行为与VBA不同?这种行为的原因是什么?
对我来说,解决方法是我DISP_FUNCTION
在调度图中附加第二个条目,该条目将分派Einfuegen
给该函数Insert
.在VBScript-Script中,我foo.Einfuegen
仍然在VBA中调用foo.Einfügen
.