I make a lot of use of the WIN32OLE library, with many thanks to Nobu
Nakada.
One of my common idioms is to take a WIN32OLE object that implements
the IEnumerable interface and extend it with the Ruby Enumerable Mix
in. Thus:
rows = @ole_worksheet.usedRange.rows.extend Enumerable
rows.select do |row|
entire_row = row.entireRow
entire_row.columns(1).text == '' and # comment
entire_row.columns(2).text != '' # no action
end
It strikes me that it might be reasonable to expect the Ruby win32ole
library to do this for me automatically. Do you agree?
Bret
on 2006-09-26 23:52
on 2006-09-27 10:22
bpettichord@gmail.com wrote: > One of my common idioms is to take a WIN32OLE object that implements > the IEnumerable interface and extend it with the Ruby Enumerable Mix > in. Thus: > ... > It strikes me that it might be reasonable to expect the Ruby win32ole > library to do this for me automatically. Do you agree? Yes, I've expected that on occasion, and I think it would be a nifty feature indeed. Enumerable's methods don't clash with common COM collection methods, as far as I can see. The reason it's not included already is that each is called as dynamically as any other OLE method; it's not determined before the call whether or not the object actually implements IEnum. So either you'd have to do this check on instantiation (probably in ole_set_member(), the function that associates a WIN32OLE object with its COM object), or you could include Enumerable in WIN32OLE itself. I'm not sure how expensive it would be in terms of performance, adding this check to ole_set_member(). Masaki Suketa? Cheers, Dave
on 2006-09-29 14:28
Hello, sorry for being too late to reply.
In message "Re: Enumerable and WIN32OLE"
on 06/09/27, Dave Burt <dave@burt.id.au> writes:
> Yes, I've expected that on occasion, and I think it would be a nifty
> feature indeed. Enumerable's methods don't clash with common COM
> collection methods, as far as I can see.
Enumerable#find method clashes the 'find' method of Excel Range object.
This is the (only) reason why WIN32OLE does not include Enumerable.
WIN32OLE class has 'each' method (WIN32OLE#each is defined),
and you can use Enumerable's methods by adding the following code.
class WIN32OLE
include Enumerable
end
Regards,
Masaki Suketa
on 2006-09-29 15:32
In message "Re: Enumerable and WIN32OLE"
on 06/09/29, Masaki Suketa <masaki.suketa@nifty.ne.jp> writes:
> In message "Re: Enumerable and WIN32OLE"
> on 06/09/27, Dave Burt <dave@burt.id.au> writes:
>
> > Yes, I've expected that on occasion, and I think it would be a nifty
> > feature indeed. Enumerable's methods don't clash with common COM
> > collection methods, as far as I can see.
>
> Enumerable#find method clashes the 'find' method of Excel Range object.
> This is the (only) reason why WIN32OLE does not include Enumerable.
Enumerable#select method clashes the 'select' method of Excel Range
object.
And I think this case is more painful than the 'find' case.
Regards,
Masaki Suketa
on 2006-09-29 18:27
Masaki Suketa wrote: >> Enumerable#find method clashes the 'find' method of Excel Range object. >> This is the (only) reason why WIN32OLE does not include Enumerable. > > Enumerable#select method clashes the 'select' method of Excel Range object. > And I think this case is more painful than the 'find' case. You're right, we don't want to break people's range.find or range.select calls (at least in Ruby 1.8). What about something like this, though? For these methods, a block is always provided. For a COM method call, a block is never provided. Why not dispatch depending on block_given? class WIN32OLE include Enumerable %w( find select ).each do |m| alias_method "enum_#{m}", m define_method m do |*args| if block_given? send("enum_#{m}", *args) {|*a| yield *a } else invoke m, *args end end end end My preference for writing code for OLE is to use uppercase method calls (range.Select) and save lowercase for Ruby methods. But this should provide compatibility for people who have range.select in their code. IEnums should have Enumerable. Cheers, Dave
on 2006-09-30 03:50
In message "Re: Enumerable and WIN32OLE"
on 06/09/30, Dave Burt <dave@burt.id.au> writes:
> What about something like this, though? For these methods, a block is
> always provided. For a COM method call, a block is never provided. Why
> not dispatch depending on block_given?
Some Enumerable's methods does not need a block, for example,
Enumerable#max.
So, I hesitate to implement your idea.
(I am not sure that there are OLE methods whose name is "max".)
> My preference for writing code for OLE is to use uppercase method calls
> (range.Select) and save lowercase for Ruby methods. But this should
> provide compatibility for people who have range.select in their code.
I prefer this approach.
In Win32OLE, WIN32OLE includes Enumerable.
If you want to call original method(range.select),
you should use range.Select.
(And Win32OLE does not provide the compatibility.
I have no idea to provide the compatibility.)
Or,
In Win32OLE, WIN32OLE does not include Enumerable.
If you want to use Enumerable's method,
you add the following code at your own risk.
class WIN32OLE
include Enumerable
end
> IEnums should have Enumerable.
I agree with you, but I have no idea that all things work well.
Regards,
Masaki Suketa
on 2006-09-30 17:06
Masaki Suketa wrote: > In message "Re: Enumerable and WIN32OLE" > on 06/09/30, Dave Burt <dave@burt.id.au> writes: > >> What about something like this, though? For these methods, a block is >> always provided. For a COM method call, a block is never provided. Why >> not dispatch depending on block_given? > > Some Enumerable's methods does not need a block, for example, Enumerable#max. > So, I hesitate to implement your idea. > (I am not sure that there are OLE methods whose name is "max".) I had an earlier version of the code I posted that went through Enumerable.instance_methods but skipped specific methods that don't need blocks (min, max, to_a, entries, grep, sort, zip, /enum_.*/, /.*\?$/). You can probably dismiss this option as well as what I wrote, just for being so inconsistent. I don't prefer this option, but I think it does strike a valuable balance between POLS and compatibility. > I prefer this approach. > In Win32OLE, WIN32OLE includes Enumerable. > If you want to call original method(range.select), > you should use range.Select. > (And Win32OLE does not provide the compatibility. > I have no idea to provide the compatibility.) I don't think this is a bad idea, but the incompatibility issue needs considering. I think it's worth it. > Or, > In Win32OLE, WIN32OLE does not include Enumerable. > If you want to use Enumerable's method, > you add the following code at your own risk. > class WIN32OLE > include Enumerable > end This (what we currently have) is deficient in the principle of least surprise and utility. You should not have to explicitly include or extend Enumerable on a WIN32OLE IEnum object. Looking at where String's going in Ruby (apparently becoming non-Enumerable in 1.9) another option could be to leave Enumerable out of WIN32OLE itself, but provide an enum method to return an enumerator object: class WIN32OLE def enum Enumerable::Enumerator.new(self) end end Cheers, Dave
on 2006-09-30 23:59
Hello,
In message "Re: Enumerable and WIN32OLE"
on 06/10/01, Dave Burt <dave@burt.id.au> writes:
> > Some Enumerable's methods does not need a block, for example, Enumerable#max.
> > So, I hesitate to implement your idea.
> > (I am not sure that there are OLE methods whose name is "max".)
>
> I had an earlier version of the code I posted that went through
> Enumerable.instance_methods but skipped specific methods that don't need
> blocks (min, max, to_a, entries, grep, sort, zip, /enum_.*/, /.*\?$/).
> You can probably dismiss this option as well as what I wrote, just for
> being so inconsistent. I don't prefer this option, but I think it does
> strike a valuable balance between POLS and compatibility.
I think I understand your code skip the methods that don't need
blocks.
But, for example, if there is an OLE methods whose name is "max",
then, I am afraid that we might have the same problem.
Which method does the following code call (in your posted code)?
OLE method max or Enumerable#max?
ole = WIN32OLE.new(...)
ole.max
Do I misunderstand you?
> Looking at where String's going in Ruby (apparently becoming
> non-Enumerable in 1.9) another option could be to leave Enumerable out
> of WIN32OLE itself, but provide an enum method to return an enumerator
> object:
>
> class WIN32OLE
> def enum
> Enumerable::Enumerator.new(self)
> end
> end
Hmm, please give me some time to investigate it.
(If there is OLE "enum" method, I think we might have the same problem
...)
Regards,
Masaki Suketa
on 2006-10-01 06:36
Masaki Suketa wrote: > Do I misunderstand you? No, that's right, that is still an issue, only for (min, max, entries, sort, grep). > Hmm, please give me some time to investigate it. > (If there is OLE "enum" method, I think we might have the same problem ...) I missed something in the Enumerator API: the method Object#to_enum does what I intended "enum" to do. Cheers, Dave
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.