anti-monk has asked for the wisdom of the Perl Monks concerning the following question:
I have searched for an answer to this problem and have not found a solution. I want to read data from a range of cells within one excel workbook and use this as an autofilter range drop down list within a cell of another workbook's worksheet.
The external data reference within the range does not work and I could not find any explicit examples of external data references within the Win32::Ole documentation. Any ideas? Thanks!use Win32::OLE qw(in with); use Win32::OLE::Const 'Microsoft Excel'; my $exceloutputfile = 'c:\workbook_out.xls'; my $Excel = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit'); $Excel->{DisplayAlerts}=0; $Excel->{Visible} = 1; my $Bookout = $Excel->Workbooks->Add(); $Bookout->SaveAs($exceloutputfile); my $excelinputfile = 'c:\list.xls'; my $Bookin = $Excel->Workbooks->Open($excelinputfile); my $Sheet = $Bookout->Worksheets("Sheet1"); $Sheet->Activate(); $Sheet->{Name} = "Sheet1"; $Sheet->Range("[list.xls]ListSheet1!a1:a99")->AutoFilter; #close and save
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Win32::Ole excel external data range
by davies (Monsignor) on Aug 06, 2010 at 18:09 UTC | |
use Win32::OLE qw(in with); What does the qw(in with) clause do? I don't really understand this aspect of Perl, and have never used it myself except by copy/paste, but I've never seen this variant used on Excel before. I wouldn't do this. I always have any "controlling" software open its own instance of Excel. What would happen if an open instance were running a long macro (some of mine have run for DAYS - literally. Yes, I hated it too)? $Excel->{DisplayAlerts}=0; Great for production code, but when debugging, I always want to know what Excel is saying to me. BTW, I assume you're using strict and all the other fruit. $Bookout->SaveAs($exceloutputfile); Why save the file now? You are going to save it later (per your comment), so you are just putting strain on the server/disc unnecessarily. There might be good reasons for this that you have cut out of your code. $Sheet->Activate(); The VBA equivalent of this litters recorded macros, but should only very rarely appear in production code. Why do you need it activated? Why can't you refer to it as $Sheet? $Sheet->{Name} = "Sheet1"; But you know its name already - that's how you set up the reference to $Sheet. Renaming it to the same name can't be what you intend. $Sheet->Range("[list.xls]ListSheet1!a1:a99")->AutoFilter; Whatever you intend, this won't do it. It's just possible that autofilter will look for a range named [list.xls]ListSheet1!a1:a99, although that's an invalid name so it can't exist. Another possibility is that it will try to read the name of the range to filter from the given range, but that can't work either as it's a multi-cell range. Most probably, this just can't work. As you may gather, I can't be sure what it is you are trying to do, but I don't think it's possible with Autofilter. Your ultimate objective is almost certainly possible, but you will need a different technique. I think what you need is advanced filters, as I said earlier, but you might want to look into dynamic named ranges as a way of managing both the data and the code. They are VERY powerful. I would also suggest recording a VBA macro that actually does what you want and then translating that to Perl. Regards, John Davies | [reply] [d/l] [select] |
by anti-monk (Initiate) on Aug 06, 2010 at 18:58 UTC | |
Thanks for the detailed response. To answer your first question, my understanding is that the qw (in with) is necessary to allow use of the in and with methods without qualifying them with the full modules name as I'm guessing that Win32::Ole doesn't export these methods automatically? I am using the with to set zoom and other page setup properties As to your other comments they are much appreciated, however many of those lines were lifted right out of the Win32::Ole tutorial. Points taken... My intention is to have drop down lists in a worksheet which are populated with data from another workbook. Maybe the only answer is to import all of the data from the other workbook into worksheets which I can set to hidden and then use advanced filters as you suggest with references to ranges within the hidden worksheets? I have been trying to use named ranges as you suggest such as $sheet->Names->Add({Name => 'IO', RefersTo => $sheet->Range("A1:A13")}); However I cannot figure out how to actually use the named range to assign data. Everytime I do something likeI get strange errors... | [reply] [d/l] [select] |
by dasgar (Priest) on Aug 07, 2010 at 04:02 UTC | |
However I cannot figure out how to actually use the named range to assign data. Everytime I do something like ... I get strange errors Two real quick points. The first deals with the usage of named ranges. Let's forget Perl for a second. In Excel, you use a named range for lookups, such as a data validation on a cell. I can't think of a scenario where it makes since to "write" data to a named range. In other words, manual data entry is done with in a single cell (or merged cells), not a named range. Secondly, are you sure you want to use \@data as the value being written into Excel? Ok, I admit that I'm not as good as I should be about reference syntax in Perl, but I believe that will return either the array address for @data or a list of it's contents. In either case, that's not what Excel would be expecting. It's expecting scalar values (strings, integers, etc) and not memory addresses or lists. Hopefully this helps you understand part of the reasons that you might be seeing some of the errors. | [reply] [d/l] [select] |
by davies (Monsignor) on Aug 07, 2010 at 18:48 UTC | |
I feared that the "with" clause was doing what you described. I don't know about other languages, but while it will compile in VB6, it won't execute twice - the second call causes a weird crash. This is documented, but I didn't find the documentation before suffering the wounds. I'm therefore very reluctant to use With except in VBA, where it works. The code I have written includes no "drop down list". This is a point on which I am unclear what you want. You could have a combobox - the sort of control you might put on a form or on the face of the spreadsheet - or you could use Data Validation of a cell. The techniques are quite different when it comes to populating the list. But since I don't know how you want the list populated anyway, I've left it out. The two techniques I have used are advanced filter and dynamic ranges. Provided users insert rows between the header and the dotted lines, the data will be handled correctly. But read up on advanced filters. Two criteria on the same line are treated as "and", while on separate lines they are "or". A blank cell matches everything, therefore a blank line will mean that nothing is filtered out. Changing the criteria will not automatically re-work the filter. In 123, this could be done by hitting {F7}, but Bill Gates knows you don't want or need this. Instead, you have to write a macro using Worksheet_Change to do all the work. Regards, John Davies | [reply] [d/l] [select] |
by davies (Monsignor) on Aug 08, 2010 at 17:14 UTC | |
Regards, John Davies | [reply] [d/l] |
by anti-monk (Initiate) on Aug 11, 2010 at 13:49 UTC | |
|
Re: Win32::Ole excel external data range
by dasgar (Priest) on Aug 07, 2010 at 03:45 UTC | |
First, I would make sure that you can do this manually in Excel. If you can't, I'm not sure how to help you get Win32::OLE to do it. (By the way, I believe that I have seen this before Excel spreadsheets, so I think it is possible.) Secondly, I would try to look at the OLE browser that is part of the Win32::OLE module and look specifically at the Excel library. Given that I don't have a good Basic/VB background, I admit that it's about like reading Greek for me. Third, try to record a macros to do what you want and then look at its source code. I don't translate the VB to Perl line by line, but it should give you an idea what needs to be done. (For example, I usually ignore the select and activation lines.) I'm out of town right now without a system that has both Excel and Perl, so I can't try testing/creating codes to help you right now. If I don't get swamped with other things, I'll try to look at this again in a few days and post some suggested code, but I make no promises. In the mean time, I hope that this information might help you down the right path to finding a solution. | [reply] |