Disconnecting from excel 2007 data source - excel

I have and excel file which is connected to an external xml file and uses it as data source
(every time I use "refresh all" it reads the xml file and updates the sheet with the data).
I want to disconnect from the data source (so that the current data will be copied to the sheet, and pressing "refresh all" will do nothing).
I tried to delete the connection from the connections list, but this DO cause an error on the next refresh (the excel is still trying to find the xml file).
I wanted to do it programmatically (in a macro), but right now I didn't even find a good way to do it in the UI.
Creating the connection differently (so that it will only copy the values in the first place) is not a good solution for me, cause I do need to refresh the data from the file before disconnecting the xml).
Thanks!!!

In Excel 2003, to disconnect the query you will need to uncheck the "Save Query Definition" checkbox option. Under the "Data Range Properties..." when you right click your imported data. I'm sure it would be similar for Excel 2007.
This code will disconnect the querytable as well if your looking to do it programatically:
Sub DisconnectQuery(sheetName As String, qryName As String)
Dim myQry As QueryTable
Set myQry = Sheets(sheetName).QueryTables(qryName)
myQry.Delete 'disconnects the querytable, data still remains
End Sub
Sub test()
DisconnectQuery "YourQuery" 'the name is found under "Data Range Properties..."
End Sub

Related

How can I post-process the data from an Excel web query when the query is complete?

As a spreadsheet developer, I am trying to stitch together two sets of rows: one from a web query to a web service I own, and the other a set of manual rows added by the spreadsheet's user (not me).
Excel's built in Web Query / Connections object only provides two modes: I can turn on "Enable background refresh" which makes the web query asynchronous, or uncheck it.
With it unchecked, Excel freezes up while the query executes, which is undesireable. With it checked, there doesn't seem to be any kind of callback or event hook available to be notified, so that I can operate against the refreshed web data.
Is there another way to do this?
An Excel web query utilizes an object called a QueryTable to carry out the business of retrieving and displaying the data.
A QueryTable can be accessed by VBA.
And just like the chart object a querytable object has events that can only be responded to by using the WithEvents keyword from a class module, like so:
Private WithEvents MyQueryTable As QueryTable
Private Sub MyQueryTable_AfterRefresh(ByVal Success As Boolean)
'Do your post processing here...
End Sub
Excel supports the ability to open a URL as another Excel workbook, via the Workbooks.Open method:
From MSDN:
Sub OpenUSDRatesPage()
Dim objBK As Workbook
Dim objRng As Range
'Open the page as a workbook.
Set objBK = Workbooks.Open("http://www.x-rates.com/tables/USD.HTML")
'Find the Canadian Dollar cell.
Set objRng = objBK.Worksheets(1).Cells.Find("Canadian Dollar")
'Retrieve the exchange rate.
MsgBox "The CAD/USD exchange rate is " & objRng.Offset(-6, -1).Value
End Sub
The call is synchronous, so you can operate on the resulting data in the new workbook immediately after the Open call.
While the workbook is loading, Excel will display a progress bar. When you're done, you can call .Close to close the web data workbook. (e.g., for the MSDN example, you'd call objBK.Close when you're done.)
The caveats of using this approach:
You're on the hook to migrate the data from the web workbook to your own (ThisWorkbook) yourself, unlike a refreshable Excel Web Query that has a set destination.
If your web endpoint has a document name that matches the name of a document open in Excel, the user will get a warning that a document with the same name is open.

Protect Excel Worksheet For Read Only But Enable External Data Refresh

I have an Excel 2010 workbook. One worksheet imports data from an external data connection (SQL query). I have also added additional columns to the worksheet to perform calculations on the data and to massage it a bit. The worksheet forms the backbone of the raw data used in the other worksheets.
I'd like to protect the worksheet to make it read-only (allowing sort, filter, pivot table usage). I know how to do this with the protect worksheet feature. But when the worksheet is protected, I can't use the Refresh button to refresh the data from the source and I want users to be able to do this. I was going to configure the connection properties to automatically refresh on open and allow manual refreshes.
Has anyone found an elegant way of enabling the protect worksheet functionality and enabling an external data refresh, without allowing users to change cell values themselves?
Based on Pankaj's suggestion I did the following (although I don't think it's very elegant and still think there must be a better way).
I created a new macro for the workbook.
Sub RefreshData()
'
' RefreshData Macro
'
Application.ScreenUpdating = False
Sheets("sheetname").Unprotect Password:="password"
ActiveWorkbook.Connections("connection name").Refresh
Sheets("sheetname").Protect _
Password:="password", _
UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
End Sub
Then I opened up ThisWorkbook in the VBA Project and edited the Workbook Open routine.
Private Sub Workbook_Open()
RefreshData
End Sub
More info about the protection options can be found here: http://datapigtechnologies.com/blog/index.php/worksheet-protection-best-practice/
It works; the sheet is locked everytime the workbook is opened and a refresh of the data is performed. The UserInterfaceOnly property doesn't make a difference to the command to refresh the data (although it should to other macro events). You will still have to specifically unlock the spreadsheet, perform the data refresh and then lock the sheet again.
I added a form button onto one of the other sheets and linked it to my RefreshData macro so that the data can be refreshed manually, while the sheet is supposedly locked.
The other thing I did in the Connection Properties, was to remove the tick against the background refresh.
An easy way to do it is to add a custom button and write a macro. When user presses the toolbar custom button, the macro behind it will unprotect the sheet and refresh the external data and then protect the sheet (with screenupdate set as false obviously)
I would suggest to add the external query on another sheet, not protected, but that you would hide.
The data on the protected sheet would simply refer to the unprotected sheet.
I added the data connection to some unprotected sheets, then hid the sheets.
Unfortunately the connections then don't work even if the structure of the workbook is protected.
I cant believe I may need to release my code un-protected, there must be an industrial strength solution to this

Excel 2010: How to change pivot table source data without disconnecting slicers?

I have researched like mad about this, and I'm worried there isn't an answer. But maybe the really smart people on this site can help.
I have two workbooks that work together - Charts.xlsm and Data.xlsm. They are always kept together in the same folder. The Charts.xlsm obviously contains all of my charts, but they are all linked to tables in Data.xlsm for their source. I also have lots of slicers in my Charts.xlsm that are connected to the charts, and they share caches when they are connected to charts with the same data source. The two workbooks are always open at the same time so that the data source reference looks like this: 'Data.xlsm'!Table1
This all works great, until I put these workbooks on another computer (which is why I am doing this so I need to find out how to fix this).
Once the workbooks are closed, the source data references change to a specific location on my harddrive: 'C:\Folder\Data.xlsm'!Table1
If I want to manually change this back to a local reference, I have to first go through and disconnect every single slicer, refresh the tables, then reconnect every slicer. Not a viable solution for my clients.
I would use VBA to change the references every time Charts.xlsm is open, but when I tried it one of two things would happen: either the workbook produced errors that would prevent saving, or Excel would crash completely.
This is the code that works perfectly for disconnecting the slicers, but produces the 'save' error:
Sub Disconnect_Slicers()
Dim oSliceCache As SlicerCache
Dim PT As PivotTable
Dim i As Long
For Each oSliceCache In ThisWorkbook.SlicerCaches
With ActiveWorkbook.SlicerCaches(oSliceCache.Name).PivotTables
For i = .Count To 1 Step -1
.RemovePivotTable (.Item(i))
Next i
End With
Next oSliceCache
End Sub
So... I am asking the Excel/VBA geniuses out there if there is any way I can maintain a relative location for my charts when they are looking for Data.xlsm so that no matter what computer I open those workbooks on, they will always be actively linked.
Thank you SO much in advance!
If always both files are in the same folder you could possibly go this way.
A. Switch off auto 'UpdateLinks' of Chart.xlsm file. You could do this once manually or, for safety reason, always when BeforeClose event fires to avoid some possible problems:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.UpdateLinks = xlUpdateLinksNever
End Sub
B. When you open Chart.xlsm change the link to Data.Xlsm using Workbook Open event + additionally refresh links. In this situation we check path to Chart.Xlsm file and search Data.Xlsm in the same folder. I assume that there is only one link to any other file otherwise some changes could be required:
Private Sub Workbook_Open()
'changing first and only one link to new one
Dim a
a = ActiveWorkbook.LinkSources
ThisWorkbook.ChangeLink Name:=a(1), _
NewName:=ThisWorkbook.Path & "\Data.xlsm", Type:=xlExcelLinks
'update the link
ThisWorkbook.UpdateLink Name:=a(1), Type:=xlExcelLinks
End Sub
I admit I do not consider all the risks therefore some test are required.

Get table data in Excel 2007 from query in Access 2007

I have an automated process that is mostly run in Access. But, in the middle, it puts some data in Excel to scrub it into the correct form (it's much faster than doing it in Access), and at the end it opens another Excel file and puts data from some Access queries into the Excel file. For these connections from Excel to Access, I accomplished them all by going into Excel and doing Data --> Get External Data --> From Access, then selecting the Access file and the query I want to get the data from and tell Excel to make it into a Table.
So, I do that one time and then I want to be able to run this automated process that simply refreshes the data. To do this refreshing of the data, I do a line like:
Worksheets("Data").Range("A1").ListObject.QueryTable.Refresh _
BackgroundQuery:=False
The problem is, half the time (and I can't figure out why it does it one time and not another), it says "Do you want to connect to path\filename?" Of course I do, how else would the table refresh? So, this stops the automation. Even if I click Yes, I still can't get it to continue on. If I click Yes, it opens up the Data Link Properties. After I click OK for that, it opens a window titled "Please Enter Microsoft Office Access Database Engine OLE DB Initialization Information". It has info in it, including the path and name of the data source I want to access, but if I click OK, it says, sorry that didn't work, would you like instead to connect to (and then it lists the exact same path and file name it just said didn't work). It repeats the steps I just mentioned, and after that it errors out.
In case it matters, here is the (basic idea) code I use to connect to Excel from Access:
Public Sub ExportToExcel()
Dim ObjXLApp As Object
Dim ObjXLBook As Object
Dim ExcelFilePath As String
ExcelFilePath = CurrentProject.Path & "\"
Set ObjXLApp = CreateObject("Excel.Application")
Set ObjXLBook = ObjXLApp.Workbooks.Open(ExcelFilePath & "filename.xlsm")
ObjXLApp.Visible = True
' Runs the "DataSetUp" macro in the Excel file.
ObjXLApp.Run ("DataSetUp")
' The DataSetUp macro saves the Excel file
' Quit Excel
ObjXLApp.Quit
' Free the memory
Set ObjXLBook = Nothing
Set ObjXLApp = Nothing
End Sub
I have no idea how to fix this! Any help would be much appreciated.
This may be happening because your access database is still open from which the new excel file needs to input data back into. The database cannot be open when this takes place, hense the reason why excel errors and asks for another location to connect to.
So, I would work on generating the needed scrubbing via vba inside access probably.

Exporting Access Query to Excel

I've got an Access 2007 database on which I have created around 15 SQL queries to process specific data, I have created a main frame navigation menu using menus in Access, I now need to extract all th queries to Excel using VBA code, I have managed to do this with the code below by creating a button and specifying this code to it.
Private Sub query1_Click()
DoCmd.TransferSpreadsheet acExport, _
acSpreadsheetTypeExcel9, "Total Users and Sessions", _
"C:\UsersandSessions.xls", , "Total Users & Sessions"
End Sub
Now my problem at the moment is that fine the query is exported to Excel, but it is done so without any formatting applied at all, I would like to add some formatting at least to the headers and maybe a title inside the spreadsheet, and one thing I dont really like is that all records are being started from the first cell. Also I would prefer that if I hit that button again in Access and the Excel spreadsheet has already exists with that query output then when clicked again it will write again to a the next available sheet.
Any suggestions or ideas a very welcome.
The short story, is you can't. You might be able to do some scripting on the Excel side to format the resulting file. If you want something pretty, you probably want to create a report.
You could, instead mount the excel sheet as a table, and then on a separated sheet in the excel file, reference the first sheet, and format the second sheet for viewing.
if you use DoCmd.TransferSpreadsheet and create an original and then edit it so that the formatting is correct, you can then run DoCmd.TransferSpreadsheet again and it will update the file with the values but keep the formatting.
However, if a human then changes the file by adding new tabs, or adding calculations, etc, then the DoCmd.TransferSpreadsheet will no longer work and will fail with an ugly error message. So what we do in our enviroment is DoCmd.TransferSpreadsheet to an original file with formatting, and follow that up in the VBA by copying the file to the users desktop, and then opening that copy so the user doesn't mess up the original source excel file.
This approach is a minimum code, clean, and easy to maintain solution. But it does require a extra "source" or original file to be hanging around. Works in Access 2007.
You also would like the results to end up on a new tab. Unfortunately, I think it will take some excel automation to do that. The VBA inside Acccess can call a function inside the VBA in Excel. That VBA could then copy the tabs as needed.
My idea would be a hybrid of Excel automation from Access and creating a template in Excel as well that would have a data table linked to your query.
To start create your data table in Excel. You can start three rows down and two columns to the right if you want or wherever. Go to your data tab and click access, find your db, choose your query you want to link to, choose table as the radio button but click properties next instead of ok, uncheck the enable background refresh, this part is critical ... under the definition tab in the connection string you will see a part that says Mode=Share Deny Write change that to Mode=Read, this will make sure that the query refreshes without errors from an MS Access VBA while the db is open and will keep your users from writing back to the db in case your query is a writeable query. Once you set that up you can adjust the table formatting however you choose from the table design tab and it will keep that formatting.
For the purposes of this we are going to assume you started the table in cell B4 ,and your named the worksheet CurrentDay, for purpose of the following VBA example be sure to replace that reference with your actual placement.
Next go back to Access and write your VBA first ensure that in your VBA window you have the reference to Microsoft Excel 12.0 Object Library is selected by going to Tools > References and selecting it from the alphabetical listing.
Create your sub as follows:
Sub query1_click()
Dim xl as Excel.Application
Dim wbk as Excel.Workbook
Dim wks as Excel.Worksheet
Dim RC as Integer
Dim CC as Integer
Set xl = New Excel.Application
Set wbk = xl.wbk.Open "X:\Filelocation\FileName.xlsx" 'name and path you saved the file you previously created
xl.Visible = True
'The above is not necessary but you may want to see your process work the first few times and it will be easier than going to task manager to end Excel if something fails.
RC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("B:B")) + 3 'This will count the rows of data in your table including your header so you can copy the data to another tab dynamically as the size of your table expands and shrinks we add 3 to it because we started at row 4 and we need the location of the last row of the record set.
CC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("4:4")) + 1 'This counts the header row and adds one space because we will use this as a location holder for our copy / paste function
Set wks = xl.wbk.Worksheets.Add
wks.Name = format(date(),"MM_dd_yy") 'this will name the tab with today's date... you can eliminate this step if you just want the sheets to be the generic Sheet1, Sheet2, etc.
With xl.wbk
.Worksheets("CurrentDay").Range(Cells(4,2),Cells(RC,CC)).Copy
.wks.PasteSpecial xlPasteValues 'This pastes the values so that the table links do not paste otherwise every tab would just refresh everyday.
.wks.PasteSpecial xlPasteFormats 'This gets your formatting.
.RefreshAll 'This will refresh your table
Wend
With xl
.Save
.Close False
.Quit
Wend
Set xl = Nothing
Set wbk = Nothing
Set wks = Nothing
End Sub
That should get you to have your data to not start on A1 of your sheets, save your old data each time, and automate the steps from access.

Resources