I can't override a table in excel using vba - excel

I have the following code in excel VBA
'Create query table to hold the rates.
With objBK.Worksheets(1)
Set objQT = .QueryTables.Add( _
Connection:="URL;https://xxx.output=XLS", _
Destination:=.Range("A1"))
End With
https://xxx.output=XLS return an XLS table that is written in A1 cell of my worksheet.
The problem is that every time I run this query it keeps adding the table in A1 shifting the previous table and NOT overriding it.
How can I override old table?

You keep adding new ones when you actually want to adjust the existing one. Give your QueryTable a name (objQT.Name = "blah"). Then when you need to adjust it, get hold of that QueryTable and make your adjustments to it.
Alternatively, just delete the old one before creating a new one.

Related

Write new row to table

I created a table in a Excel sheet (named Table1) with a header and a blank row. I can display it in a listBox on my form.
If I add a cell in the Excel table, I can display new cells when my script is running.
When I try to add a new cell with VBA, I have an error.
Dim MyTable as ListObject
Dim newRow as ListRow
Set myTable = Sheets("Sheet1").ListObjects("Table1")
nbLine = myTable.ListRows.Count
myTable.ListRows.Add
When I run this, nbLine writes the right number of lines of my table. But, when I run the ListRows.Add, I have the error
'Method 'Add' of object 'Listrows' failed'
and Excel crashes.
I tried myTable.ListColumns.Add and it works. It creates a column at the end of my table.
Why doesn't ListRows.Add work?
Also after creating a row, I want to add content to each column of my new row. I didn't find any command to do that. I found on the Microsoft documentation the property DataBodyRange but it only works in reading, not in writing.
How can I write to my table?
Finally, I tried on a new workbook and it works fine. After renaming the new worksheet, it works. But after renaming the table, it didn't work. I then found that if I put an underscore '_' in the name of the table, the instruction listrows.add wont work. If I delete the underscore, the instruction works fine !
My problem appears because I put an underscore into my table's name.
After searching more similar subjects, I found this one: Excel VBA adding new row in table (excel crashing)
The listrows.add wont work because the table is linked to a combobox. If you break the link in the form and create the link by code when launching the application, everything will work !

Select - Visible Cells - Excel Office-JS

I'm working a subroutine which does filtering via hiding rows/cols. I realized that the end user if they copy data, will copy the hidden rows.
I'd like to just have my routine finish by having those cells selected, but I tried used rng.select(); w/ both visibleview and specialcells but both error saying select isn't approriate for that object.
var usedrng = ws.getUsedRange(true).getSpecialCells("Visible");
var usedrng = ws.getUsedRange(true).getVisibleView()
I'm resorting to coping the data to a new worksheet, but wondered if there was a way because I saw this quote:
Non-continuous selections are not only not supported in Office.js (for
Word, we DO support them for Excel though)
Update: I found a workaround that I'm happy with, but I'll leave question as my workaround requires turning on filtering which may not be desired. In my case, I wasn't filtering due to needing multiple criteria's more then filter can handle.
My workaround is to use my normal function to hide rows. Then grab getVisibleView and push filter column values to Array. I then unhide rows and apply a filter on values with that array of items.
You can then use getUsedRange(true) and select. When I used CTRL + C only the visible cells were selected as per normal filtering copy/paste SOP. This enables me not to have to copy data to a new WS and leave the existing WS active.

Excel - How to update picture of table based on changes

I have a table "A" that allows user input and the changes the user makes will affect table "B" in an other sheet. I'm looking for a way to put a picture of that table B next to table A. I cannot put table B directly next to the table A as it has hidden rows.
I want to create a macro that converts table B into a picture and posts it next to the table A. Once the user makes a change, the old picture will be deleted and an updated version will be posted. Is there a way to do this? Thank you in advance!
This is my current code:
Call Sheet1.Range("A1:E12").CopyPicture(xlScreen, xlPicture)
Sheet2.Shapes.AddChart
Sheet2.Activate
Sheet2.Shapes.Item(1).Select
Set objChart = ActiveChart
objChart.Paste
When I run it I get the error "Run-time error 91: Object Variable or With block variable not set" but an chart does appear.
Why a picture? If so, every time changes are made, with vba, print the area of the table to a .pdf or .xps and then paste it next to your table in sheet one.
Else just make references to the first sheets values so when entered the second one changes aswell? i.e. "=Sheet1!C6"
Might have missunderstood something please let me know.

Updating DataSource of PivotTables via VBA, without creating new PivotCaches

I have a workbook, where there is a RawData sheet and there are 8-9 other sheets that have pivot tables that read a table from RawData. The RawData changes daily, i.e. there can be more or less number of rows in the RawData sheet's table.
Right now, I manually update DataSource property of each pivot table one each sheet using ChangeDataSource feature of Excel. However, this is painful. Crawling on web I found vba code to update all Pivot tables at once. I am not pasting the whole code, but it looks something like this.
ActiveSheet.PivotTables("PivotTable1").ChangePivotCache ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=<RawData-AddressRange>)
But what this code does is, it creates new pivot caches for each pivot table and increases the size of the file. However, I do not want the file size or number of pivot cache's to increase, but just change the dataSource of existing PivotTables/PivotCaches and refresh them.
To set a single PivotCache for all the PivotTable:
Sub UpdatePivots()
Dim ws As Worksheet, pivot As PivotTable, cache As PivotCache
' create a new pivot cache '
Set cache = ThisWorkbook.PivotCaches.Create( _
XlPivotTableSourceType.xlDatabase, _
ThisWorkbook.Sheets("Sheet1").UsedRange)
' set the pivot cache for each pivot table
For Each ws In ThisWorkbook.Worksheets
For Each pivot In ws.PivotTables
If cache.Index Then
pivot.CacheIndex = cache.Index
Else
pivot.ChangePivotCache cache
End If
Next
Next
' refresh the cache
cache.Refresh
End Sub
Just turn RawData into an Excel Table (Ctrl + T is the keyboard shortcut) and then point your PivotTables at that Table. (You'll have to use the 'Change Data Source' button one more time, to get it to change from using a hard-coded reference like $A$1:$Z$1000 to a Table reference like Table1).
From then on, any time you put new data into RawData, the Table will automatically expand (or contract) to accomodate it, and whenever you click refresh, the PivotTables will automatically reference those Tables instead of a hard-coded range.
Also note that if the PivotTables are all based on the exact same data source, refreshing one of them refreshes all of them.
You should consider using dynamic named range to define your RawData. Set the data source of all of your pivot tables to be your dynamic named range and then all you will need to do is click data>refresh all to update all pivot tables
here is a tutorial on dynamic named ranges
http://www.excel-easy.com/examples/dynamic-named-range.html

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