.Select, .Activesheet, .Activecell etc... - vba
For this question, I refer to the post below to clarify myself:
Why is my conditional format offset when added by VBA?
In many, many posts I see these days, OP's are silently allowed to use .Activate, .Select, .Offset, etc... while they are an open door to potential bugs (most often caused by the end users).
The code is sometimes even supported.
My question: Is there one valid situation where you would use any of these statements without direct alternatives being available that catch typical bugs resulting from these stmts?
I'm referring to dynamic solutions that in my opinion are a must when developing for Excel.
Personally, in more than 6 years I can't remember a single case where I needed it; it seems always to be one of the the worst options available. In my previous company, it was a silent rule never to use it and it only made my VBA life (and that of the end user) better.
Why I create this question is because I think that it is worthful to make newcomers into VBA aware of the risks they take when using these statements (by experience proven risks when the End Users do something unexpected - in the end they don't have any affection with VBA) and to propose direct alternatives (I won't state I always did that before myself, but I feel in my gut that there is something wrong with just offering quick solutions on already bug monsters).
I believe that when silently allowed (which it automatically enhances in this case), starting VBA developers will create a growing amount of tools the wrong way (and thus also newcomers will inherit the behaviour - which they will also learn from Stack Overflow since Google returns the results they look for (!)).
If the developer is not aware why he "can" use a "select" and in which situations it is a potential bug, (s)he should never use it imho. Personally I might use the select stmt in the immediate window to do some quick checks on dynamic range definition (bug mode), but not in written code.
The result makes VBA in the end even more unpopular than it is already; the language will be made the victim in case trouble appear (yet it is imho still the "best" programming support available for the Excel and Access applications). I've seen this happen too many times in a large company where VBA is always "shit".
This is only my own honest experience.
It is not a question of being right or wrong; I am interested in hearing your point of view on the question.
I agree about Select and Activate, but not ActiveWorkbook, ActiveSheet, and ActiveCell (I agree that they are abused, but not that they should be avoided, per se). There are definitely legitimate uses for those. I have a program that automates a "fill series" that does so from the ActiveCell. My program can't predict what cells will be used; it's up the user to select it. That's part of the user interface.
However, there are three situations where I have had to use Select (now four that I read about zoom, but I don't ever use it).
Conditional Formatting. There is a work around using Application.ConvertFormula, but it's worse than just storing the selection, selecting the right cell, doing the deed, and reselecting the previous selection.
Data Validation. Same reason.
Shapes. I wish I could remember the details, but it's been too long since I've worked with Shapes. There was something I couldn't do without selecting the shape first.
Ridding code of Select and Activate is a noble fight.
There are a few methods in Excel that require Activate or ActiveSheet/ActiveWorkbook etc as I've been caught with a gotchas on occasion. The only one I can remember at the moment is the zoom property. Zoom affects only the sheet that's currently active in the window so to zoom all sheets you would need something like
Sub SetZoom()
Dim ws As Worksheet
Application.screenupdating = false
For Each ws In Worksheets
ws.Select
ActiveWindow.Zoom = 80
Next ws
Application.screenupdating = true
End Sub
You can use .Select to determine what a user's view is after running code - for example if you create a new workbook in your code, without using Activate or Select your user may not know this happens.
I frequently end a long operation creating a new workbook or other largescale data manipulations with
FinalViewWorkbook.FinalViewSheet.Range("A1").Select
Just to inform the end user about something - "oh, this created a new workbook of reports!" etc.
I think it is important in this matter to distinguish some:
Active-something: Only use this if it is absolutely necessary to know what the user is handling right now. In my experience, this is usually Data Validation or Active Sheet Detection (e.g. "Update the Sheet where the user just pressed a button").
Selection: Somewhat the same as Active, only use readingly. Userful either for Data Validation, or for gimmicks like "Interpret the cell value as path and open it in a new Explorer Window".
Select, Activate: Imho different from Selection, as it actually changes the selected Cell, Sheet etc. Never ever use this to read or write data, since it enables a user to mess up your program by just clicking. Users love to click. Only use this to Zoom (see answer by #user3357963) or clean up a view after your code has finished working (see answer by #enderland). (I'm not sure, but I think handling the PageView also requires ActiveSheet).
Select, Activate the 2nd: If you are new to VBA and are learning via Macro Recorder, you will find a lot of code generated like this:
First Range("A5").Select, then Selection.Value="NewValue". Join this to Range("A5").Value="NewValue".
Offset: Personally, I don't have a problem using .Offset() - I never encountered problems with this command. Instead, I think it's a handy way of saying "The cell next to this" without having to go through "This cell's sheet at this cell's row and column+1" every time.
In many, many posts I see these days, OP's are silently allowed to use .Activate, .Select, .Offset, etc...
I agree with this. Even though it's easier to just give the necessary answer to make a piece of code work, the use of ActiveCell.Value and the like should be discouraged. This will be much easier if there's a well explained Thread to link to, as this here is hopefully becoming :-)
From my perspective, with few exceptions, the only time you should use Select is as a user input, and only then after careful consideration of alternative design/UI requirements.
For example, I'd say it's generally not advisable to rely on Selection to let user define a Range object when this method keeps execution within the code:
Dim myRange as Range
Set myRange = Application.InputBox("Select your range", Type:=8)
However, if you need to prompt users to select a particular shape or object on the worksheet, then maybe it's better to let them make a Selection (however, this can open up a Pandora's Box of problems without good error-handling and logic to prevent undesired user actions...).
Here is an example of one such exception that I have in PowerPoint. I have some RibbonUI XML and VBA that adds buttons to the Shapes right-click context menu in PowerPoint, and adds similar buttons to the Ribbon itself. These are seamless UI that give the end-user a more "native" experience with the application -- users want to be able to right-click the chart and then run some macro procedures against that selected chart or table, etc. They don't want to press a button to open up a user form and scroll through a listbox of generic shape names or GUIDs.
The procedure code needs to examine the Selection in order to handle it properly so I can use something like below, where
Sub UpdateOrEditSelection(update As Boolean)
'This procedure invoked when user edits/updates a chart.
Dim uid As Variant
Dim sel As Selection
Dim s As Integer
Dim chartsToUpdate As Object
Dim multipleShapes As Boolean
Dim sld As Slide
Set sel = ppPres.Windows(1).Selection
If update Then
Set chartsToUpdate = CreateObject("Scripting.Dictionary")
Select Case sel.Type
Case ppSelectionShapes
For s = 1 To sel.ShapeRange.count
uid = sel.ShapeRange(s).Name
'....
'...
'..
'.
Next
Case ppSelectionSlides
For Each sld In sel.SlideRange
For s = 1 To sld.Shapes.count
uid = sld.Shapes(s).Name
'....
'...
'..
'.
Next
Next
Case ppSelectionText
s = 1
If sel.ShapeRange(s).HasTable Or sel.ShapeRange(s).HasChart Then
uid = sel.ShapeRange(s).Name
'....
'...
'..
'.
End If
End Select
'....
'...
'..
'.
Where does it come from?
The Macro Recorder. Essentially, this feature records every literal user input: scrolling, selecting, viewing, activating, default properties, etc., to the point of overkill. While this is sometimes helpful, it does encourage bad code written by people who don't know that it's bad, but I will not belabor that point which has been made here:
How to avoid using Select in Excel VBA macros
What is better, conceptually?
Program to the objects directly. If you're merely using VBA to mimic keystrokes and mouseclicks, you're doing it wrong.
Exceptions:
I've found when applying formatting to series data in charts, where Select is occasionally necessary. This seems IMO to be a bug with Excel and not a design feature.
Other applications (because VBA is not only Excel):
Word is a different animal, which relies a lot more on Selection object
In PowerPoint there are some sort of operations that can only be performed when the application and slide/shape are visible or otherwise in view. While you don't usually need to "select" anything, it does require more cumbersome code.
I found this snippet in my App:
Set tb = cht.Shapes.AddTextbox(msoTextOrientationHorizontal, ptLeft, tBoxTop, ptWidth, ptHeight)
tb.Select '<--- KEEP THIS LINE OTHERWISE TEXTBOX ALIGNMENT WILL NOT WORK ## ## ##
And this:
'PPT requires selecting the slide in order to export an image preview/jpg
sld.Select
ppPres.Windows(1).View.GotoSlide sld.SlideIndex
sld.Shapes(1).Chart.Export imgPath, ppShapeFormatJPG
And this, dealing with individual Point objects:
pt.Select
pt.format.Line.Visible = msoTrue
pt.format.Line.Visible = msoFalse
pt.MarkerSize = pt.MarkerSize + 2
This is not an exhaustive list, just some examples of exceptions that I found. While these were from PowerPoint, the charts in PowerPoint use the same object model as Excel so I would not be surprised if some of these also need to be hacked in Excel, and Word, too.
Outlook: I don't do much with Outlook, it is a lot like Word and actually uses the Word object model in the Inspector, but what little I do with Outlook does rely on things like ActiveInspector, etc.
Neither Word or PowerPoint have a "macro recorder" anymore (actually, I think Word might but it's so damn impotent as to be useless) and by the time most people do any development in other applications, they've figured most of this out already.
Related
Is there a way in VBA to iterate through specific objects on a form?
I would like to have a subroutine in VBA that conditionally changes the Enabled property of each of 20+ buttons on a form via iteration rather than code them all by hand. These buttons are named similar to tables that they process. For example: A table to process is called "CUTLIST"; its corresponding button is called "but_CUTLIST". There is another table that holds the list of tables to be processed (used for iteration purposes in other subs). What I have so far... Private Sub txt_DataSet_GotFocus() Dim sqlQry as String Dim butName As String Dim tableList As Recordset Dim tempTable As Recordset Set tableList = CurrentDb.OpenRecordset("TableList") 'names of tables for user to process tableList.MoveFirst 'this line was corrected by moving out of the loop Do Until tableList.EOF sqlQry = 'SQL query that determines need for the button to be enabled/disabled Set tempTable = CurrentDb.OpenRecordset(sqlQry) If tempTable.RecordCount > 0 Then 'begin code that eludes me butName = "but_" & tableList!tName Me(butName).Enabled False 'end code that eludes me End If tableList.MoveNext Loop End Sub If I remember correctly, JavaScript is capable of calling upon objects through a variable by handling them as elements of the document's object "array." Example: this[objID]=objVal Is such a thing possible with VBA or am I just going about this all wrong? Viewing other questions... is this what's called "reflection"? If so, then this can't be done in VBA. :( In case more explanation helps to answer the question better... I have a utility that runs SQL queries against a pre-defined set of tables. Each table has its own button, so that the user may process a query against any of the tables as needed. Depending on circumstances happening to data beforehand, any combination of the tables may need to be queried via pressing of said buttons. Constantly referring to the log, to see what was already done, gets cumbersome after processing several data sets. So, I'd like to have the buttons individually disable themselves if they are not needed for the currently focused data set. I have another idea on how to make that happen, but making this code work would be faster and I would learn something.
I'm not an expert on VBA, but I would re-arrange the code to take advantage of the fact that you can iterate through the control collection in the user form Something like this: Dim ctrl as Control For Each ctrl in UserForm1.Controls If TypeName(ctrl) = "Button" Then ctrl.Enabled = True End If Next You can pass the button name to some other function (from this loop) to determine whether the button in question should be enabled / disabled.
Directly referencing userform entry in VBA instead of passing value to a variable
folks. I am new to programming, but I am writing some macros to help manage a shared Excel workbook for my job. I am implementing a few different user roles for people who need to access this workbook. The security is not very critical, just to prevent people from accidentally making (and saving) changes to things they shouldn't be. I am just having a UserForm prompt for the password and, based on what's entered, grant the proper access. I have it written so that the user's entry into textbox on the UserForm is referenced directly as Me.textboxPasswordEntry.Value for any comparisons. It occurs to me that this may not be best practice, but I can't put my finger on why. Maybe I'm just over thinking? At the same time, it seems silly and wasteful to declare a variable, pass the value to the variable, and then analyze that. The Sub below is from the UserForm, and I've included it to show you what I mean. This is a very straight-forward scenario, I know, but am I courting trouble if I continue this practice through more complex ones? If so, what kind of problems might I run into? Thanks. Private Sub buttonOK_adminPW_Click() 'The subs SetUserType_[level] are in the ChangeUserType module 'AdminPass and DesignPass are module-level variables set on UserForm initialization 'Default user type is User. Read-only access. 'Admins can edit the workbook, but must save via a macro to ensure ' things are reset properly for Users (some sheets hidden, etc.) 'Designers can edit the workbook, but also have full ability to save using ' the regular file menu/ctrl+s/etc. Application.ScreenUpdating = False Select Case Me.textboxPasswordEntry.Value Case AdminPass 'Shows right control buttons and unlocks the wkbk for admin access SetUserType_admin Unload Me Case DesignPass 'Shows all control buttons and unlocks the wkbk for designer access SetUserType_design Unload Me Case Else MsgBox ("Password incorrect. Please retry.") With Me.textboxPasswordEntry .Value = "" .SetFocus End With End Select Application.ScreenUpdating = True End Sub
Yeah I've also pondered over "best practise" with userforms over the years... I guess it's just through experience that I use approach below most often: Use as little code as possible in the userform itself (thinking is, the form is more "reusable" if it does as little as possible back to its parent... its reason for existance is just to get input) Do use code on the "activate" event of the form to clear all the fields on the form (this makes sense to be in the form because then you don't need to remember every control on the form to clear at every point you use it) Either directly reference objects from the form in your calling code (i.e. stPassword = userform1.tbPassword.value) or... Use "public" variables in the userform ... i.e. before all code in userform declare "public stPasswordInput as string" then you can reference in your calling code with e.g. stPassword = userform1.stPasswordInput I'm keen to see what other people suggest though!
Wait until ActiveWorkbook.RefreshAll finishes - VBA
I have a sub that calls on ActiveWorkbook.RefreshAll to bring new data in from an XML source, and then performs multiple modifications to it. The problem is that not enough time is given for the RefreshAll command to finish, so the following subs and functions end up not executing correctly, which result in repeated rows not being correctly erased. I have tried using Application.Wait and the Sleep function, but they seem to pause the refresh process too. I simply want the rest of the code to wait until the refresh process finishes before executing the rest of the code. Any ideas on how to implement this? Right now I was only able to fix it by not calling on RefreshAll, which gives me the idea of implementing a second flow to be executed afterwards, but that's not a good workaround. Please let me know if any of this wasn't clear. Thanks EDIT So I tried a few suggestions from the posts below, and this is what I was able to come up with. Doing a "record macro" and then UNCHECKING the "Enable background refresh" in the table properties did not result in anything. I did a refresh as well afterwards. This was the result of the recorded macro: With ActiveWorkbook.Connections("XMLTable") .Name = "XMLTable" .Description = "" End With ActiveWorkbook.Connections("XMLTable").refresh The class ActiveWorkbook.Connections does NOT have a BackgroundQuery option so that I can set it to False. Any ideas? Just to be clear. This is an XML file hosted on a website which Excel goes and imports into a table. I then call that data into a pivot and other things. The goal here is to allow the import process from the website to the table to finish BEFORE executing any other commands. Thanks EDIT2: After a little more research, I have found this page: http://www.mrexcel.com/forum/excel-questions/564959-execute-code-after-data-connection-refresh-finished.html It appears that an XML type of connection does not have a BackgroundQuery boolean. That option is only available for ODBC and OLEDB connections, which are types xlConnectionTypeODBC and xlConnectionTypeOLEDB, respectively. The XML connection I am using is of type xlConnectionTypeXMLMAP which does not have a BackgroundQuery option. Does anyone have any idea on where to go from here? The only solution I have in mind right now is to make two seperate macro buttons on the excel sheet, one for refreshing and one for data modification, but I'd rather keep that option to the very last.
I had the same issue, however DoEvents didn't help me as my data connections had background-refresh enabled. Instead, using Wayne G. Dunn's answer as a jumping-off point, I created the following solution, which works just fine for me; Sub Refresh_All_Data_Connections() For Each objConnection In ThisWorkbook.Connections 'Get current background-refresh value bBackground = objConnection.OLEDBConnection.BackgroundQuery 'Temporarily disable background-refresh objConnection.OLEDBConnection.BackgroundQuery = False 'Refresh this connection objConnection.Refresh 'Set background-refresh value back to original value objConnection.OLEDBConnection.BackgroundQuery = bBackground Next MsgBox "Finished refreshing all data connections" End Sub The MsgBox is for testing only and can be removed once you're happy the code waits. Also, I prefer ThisWorkbook to ActiveWorkbook as I know it will target the workbook where the code resides, just in case focus changes. Nine times out of ten this won't matter, but I like to err on the side of caution. EDIT: Just saw your edit about using an xlConnectionTypeXMLMAP connection which does not have a BackgroundQuery option, sorry. I'll leave the above for anyone (like me) looking for a way to refresh OLEDBConnection types.
Though #Wayne G. Dunn has given in code. Here is the place when you don't want to code. And uncheck to disable the background refresh.
DISCLAIMER: The code below reportedly casued some crashes! Use with care. according to THIS answer in Excel 2010 and above CalculateUntilAsyncQueriesDone halts macros until refresh is done ThisWorkbook.RefreshAll Application.CalculateUntilAsyncQueriesDone
You must turn off "background refresh" for all queries. If background refresh is on, Excel works ahead while the refresh occurs and you have problems. Data > Connections > Properties > (uncheck) enable background refresh
Here is a solution found at http://www.mrexcel.com/forum/excel-questions/510011-fails-activeworkbook-refreshall-backgroundquery-%3Dfalse.html: Either have all the pivotcaches' backgroundquery properties set to False, or loop through all the workbook's pivotcaches: Code: For Each pc In ActiveWorkbook.PivotCaches pc.BackgroundQuery = False pc.Refresh Next this will leave all pivotcaches backgroundquery properties as false. You could retain each one's settings with: Code: For Each pc In ActiveWorkbook.PivotCaches originalBGStatus = pc.BackgroundQuery pc.BackgroundQuery = False pc.Refresh pc.BackgroundQuery = originalBGStatus Next
This may not be ideal, but try using "Application.OnTime" to pause execution of the remaining code until enough time has elapsed to assure that all refresh processes have finished. What if the last table in your refresh list were a faux table consisting of only a flag to indicate that the refresh is complete? This table would be deleted at the beginning of the procedure, then, using "Application.OnTime," a Sub would run every 15 seconds or so checking to see if the faux table had been populated. If populated, cease the "Application.OnTime" checker and proceed with the rest of your procedure. A little wonky, but it should work.
Try executing: ActiveSheet.Calculate I use it in a worksheet in which control buttons change values of a dataset. On each click, Excel runs through this command and the graph updates immediately.
This worked for me: ActiveWorkbook.refreshall ActiveWorkbook.Save When you save the workbook it's necessary to complete the refresh.
Here is a trick that has worked for me when some lines of VBA code have trouble executing because preceding lines haven't completed doing their thing. Put the preceding lines in a Sub. The act of calling the Sub to run those lines may help them finish before subsequent lines are executed. I learned of this trick from https://peltiertech.com/ and it has helped me with timing issues using the Windows clipboard.
If you're not married to using Excel Web Query, you might try opening the URL as a separate Workbook instead. Going that route lets you work on the resulting data once the web request completes, just like if you turn off "Enable background refresh." The nice thing is though, Excel displays a progress bar during the request, instead of just freezing up / showing a load message in the destination cell. See my answer on this question: How can I post-process the data from an Excel web query when the query is complete? The tradeoff of that approach is you have to manage processing the data you get back yourself - Excel won't put it in a given destination for you. We ended up going this route after we tried something pretty similar to what you seem to have been doing.
I was having this same problem, and tried all the above solutions with no success. I finally solved the problem by deleting the entire query and creating a new one. The new one had the exact same settings as the one that didn't work (literally the same query definition as I simply copied the old one). I have no idea why this solved the problem, but it did.
I tried a couple of those suggestions above, the best solution for me was to disable backgroundquery for each connection. With ActiveWorkbook.Connections("Query - DL_3").OLEDBConnection .BackgroundQuery = False End With
For Microsoft Query you can go into Connections --> Properties and untick "Enable background refresh". This will stop anything happening while the refresh is taking place. I needed to refresh data upon entry and then run a userform on the refreshed data, and this method worked perfectly for me.
I have had a similar requirement. After a lot of testing I found a simple but not very elegant solution (not sure if it will work for you?)... After my macro refresh's the data that Excel is getting, I added into my macro the line "Calculate" (normally used to recalculate the workbook if you have set calculation to manual). While I don't need to do do this, it appears by adding this in, Excel waits while the data is refreshed before continuing with the rest of my macro.
For me, "BackgroundQuery:=False" did not work alone But adding a "DoEvents" resolved problem .QueryTable.Refresh BackgroundQuery:=False VBA.Interaction.DoEvents
I know, that maybe it sounds stuppid, but perhaps it can be the best and the easiest solution. You have to create additional Excel file. It can be even empty. Or you can use any other existing Excel file from your directories. 'Start' Workbooks.Open("File_where_you_have_to_do_refresh.xlsx") Workbooks("File_where_you_have_to_do_refresh.xlsx").RefreshAll Workbooks.Open("Any_file.xlsx) 'Excell is waiting till Refresh on first file will finish' Workbooks("Any_file.xlsx).Close False Workbooks("File_where_you_have_to_do_refresh.xlsx").Save or use this: Workbooks("File_where_you_have_to_do_refresh.xlsx").Close True It's working properly on all my files.
What I've done to solve this problem is save the workbook. This forces it to refresh before closing. The same approach works for copying many formulas before performing the next operation.
VBA - Unable to get TextBoxes Property of Worksheet Class
Fairly new to VBA and I just started encountering the error Unable to get TextBoxes Property of Worksheet Class. It highlights the following line: ActiveSheet.TextBoxes("txtFilePath").Text = Application.ActiveWorkbook.Path & "\" The mystery to me is that I know this line was working before without any problems. The only thing I could think of is that I was messing with protecting the sheet, but even now that it is unprotected I still get the error. I've also tried the following solution, but encounter the same error: ActiveSheet.OLEObjects("txtFilePath").Object.Text = Application.ActiveWorkbook.Path & "\" Can anyone explain to me why I am encountering the error and why I started encountering it so randomly? How can I fix it?
Sadly enough, there is no clear way on how to access the properties of a grouped shape (a group is basically a shape, at least in 2010). There are two possible solutions to go about this. One is obviously to ungroup the textboxes, access the textbox in question and modify it, then regroup them. However, this will prove to be difficult to track as the Group number increases with every regroup that you do. This can pose a potential problem if you have multiple groupings. The other way, surprisingly enough, is to do it the 'dirty' way, which is basically what the macro recorder gives us in a nutshell. The way to do it is to select the shape itself and to change the text directly, emulating a direct click-and-type motion manually. I've tested it and it works, even when the textbox in question is grouped multiple times. Sub Macro3() foo = Application.ActiveWorkbook.Path & "\" ActiveSheet.Shapes.Range(Array("txtFilePath")).Select Selection.ShapeRange(1).TextFrame2.TextRange.Characters.Text = foo End Sub
Sorry to answer my own question. Figured it out by accident. The problem was that I had my textbox (txtFilePath) grouped together with another textbox on my worksheet. When I ungrouped them everything worked fine. Can anyone explain to me why the grouping would make a difference?
How do I use Google.GData.Client.AtomLinkCollection.FindService method to get the list of worksheets in a Google Spreadsheet?
I'm trying to write code that talks to Google Spreadsheets. We do a bunch of processing on our end and then pass data out to our client into this spreadsheet and I want to automate it. This seems like it should be easy. On this page, Google says "Given a SpreadsheetEntry you've already retrieved, you can print a list of all worksheets in this spreadsheet as follows:" AtomLink link = entry.Links.FindService(GDataSpreadsheetsNameTable.WorksheetRel, null); WorksheetQuery query = new WorksheetQuery(link.HRef.ToString()); WorksheetFeed feed = service.Query(query); foreach (WorksheetEntry worksheet in feed.Entries) { Console.WriteLine(worksheet.Title.Text); } Following along at home, I start with: Dim link As AtomLink = Entry.Links.FindService(GDataSpreadsheetsNameTable.WorksheetRel, "") Dim wsq As New WorksheetQuery(link.HRef.ToString) and when execution gets to that second line, I find that "Object reference not set to instance of an object." The FindService method is returning nothing. And when I look at GDataSpreadsheetsNameTable.WorksheetRel, it's a constant value of "http://schemas.google.com/spreadsheets/2006#worksheetsfeed" I'm not really at the point where I even grok what it wants to be doing. E.g., what's a feed? Is a worksheet really what I think it is based on Excel nomenclature? That kind of stuff. But I see a couple of things that might be causing my issue: The C# method call "...FindService(GDataSpreadsheetsNameTable.WorksheetRel, null);" I'm not sure about that null. It demands a string, so I used "" in my VB, but I'm not sure that's right. That schemas.google.com URI doesn't seem to be live. At least, if I punch it into a browser, I get server not found. But again, I don't exactly know what it's trying to do. So, any thoughts? Anyone have VB code that reads Google Spreadsheets and time to instruct a newbie? I'm surprised to find that there's essentially no useful sample code floating around the net. Thanks for reading!
So, of course, right after I posted this I found some inspiration over here. Manually iterating across the collections works just fine, even if it's not the preferred way to do this. I'm still keen to hear info from others related to this, so feel encouraged to help out even though I'm maybe over this one hurdle. For Each Entry In mySprShFeed.Entries If Entry.Title.Text = "spreadsheetNameSought" Then For Each link As AtomLink In Entry.Links If link.Rel = GDataSpreadsheetsNameTable.WorksheetRel Then Dim wsf As WorksheetFeed = service.Query(New WorksheetQuery(link.HRef.ToString)) For Each worksheet In wsf.Entries Console.WriteLine(worksheet.Title.Text) Next End If Next End If Next