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.
Related
I have made an userform excel system to SignUp or Login users to a kind of quizz. All this files are available on sharepoint of my company to be run. When someone SignUp, all information he had written in the userform are sent to an external workbook that gathered all users inscriptions. All works find individually, but when two people or more are submitting their signup data barely at the same time, their is a conflict in the external workbook because the users overwrite what the earliest one as putted into the cells while I asked to write in the next empty row. I think this is because, the external workbook has not the time to update on SharePoint what the very previous user as written.
To avoid this trubble, I have decide the CheckOut if an other user is already writting in the external workbook. However, I have a kind of similar issue with the CheckOut VBA code lines I used below. When the two users send their data barely at the same time, they come togather in the "CanCheckOut", then one of them succed to checkout the workbook, but the other one is bring to a message box who say "The workbook is already checkout. Would you like to open the file as readOnly or cancel file opening". My wish is that that only one of the users enter in the "If CanCheckOut Then", or to close automaticaly in VBA the messagebox for the second user trying to checkin. I don't know if I can avoid the two users to come inside this "if" because it could a standard lag of syncronisation due to SharePoint. So I tryed the second solution that is to close automaticaly in VBA the messagebox for the second user trying to checkin, however it seems that "Application.DisplayAlerts = False" or "On Error GoTo ErrorUser" don't work so I am kind of stuck and looking for your help and your experience in VBA with multi-users configurations on SharePoint to solve this issue.
Sub UseCheckOut()
Dim App As New Excel.Application
Dim wBook As Excel.Workbook
Dim FileNameUser As String
FileNameUser = ThisWorkbook.Path & "/Support/UsersData.xlsm"
If Workbooks.CanCheckOut(FileNameUser) = True Then
Workbooks.CheckOut FileNameUser ' When two users run the code simultaneously they
' both come to this line
Set wBook = App.Workbooks.Open(FileNameUser)
Else
MsgBox "Someone else signup to the quizz. Please, submit you registration again"
Exit Sub
End If
End Sub
I have an excel file stored in Sharepoint (which is also accessible with Microsoft Teams), with the path: https://organization.sharepoint.com/PathOfFile/myFile.xlsx
The file can be edited by multiple at the same time with the co-authoring feature in Sharepoint.
I want to use another excel file stored locally in my computer to access and modify the one in Sharepoint. This local file has a button with this VBA code in it:
Sub UpdateSP():
f_name = "https://organization.sharepoint.com/PathOfFile/myFile.xlsx"
Workbooks.Open f_name
Workbooks("myFile.xlsx").Activate
ActiveWorkbook.Sheets("sheet1").Activate
Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.Value = 9999
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = 0000
ActiveWorkbook.Close SaveChanges:=True
End Sub
In principle it works, the file in Sharepoint is modified. But things go wrong if there's someone editing the file while I run the code, then two versions of the file seem to be created, one for the online-live editing, and the one for my code.
If this happens, the online version of the file won't show the changes made by the code, and whenever the file is opened with the excel app, a pop-up will show asking which version of the file should be kept, losing all the changes done in the disposed version.
I have tried to use the CanCheckOut and CheckOut methods, but CanCheckOut always returns False for whatever reason (there are some questions here with the same issue but I havent been able to find a solution).
Can someone suggest a solution to this issue? Thanks.
I'm not 100% sure it will work on SharePoint, but in theory, ADODB is a library for VBA that has the syntax of objects to use Microsoft's Jet Engine so you can open files AdLockOptimistic---ally. ((look up lock types in ADO.net))
This works on a file directory basis, so if the DB being modified is open, it will handle the update.
Instead of using Excel's Application to open the file, you would establish an ADO connection, and then specify the type of Lock in order to access the Excel's sheets and tables inside it.
This works for shared / network drives, so I'm guessing since SharePoint can be mapped as a file explorer drive, then ADO should work and is worth a try.
Here's a basic example to get you started: ADO question
Try enabling the autosave after activating the workbook.
To do so, add this line:
ActiveWorkbook.AutoSaveOn = True
after the Workbooks("myFile.xlsx").Activate line.
I have had similar issues with collaborative files and making sure the autosave is enabled has solved it.
To be able to incorporate changes that way your code must run inside a coauthoring context.
Instead of opening the document from another doc or local copy, the code must be running inside the same document being opened from the same source URL (Sharepoint or OneDrive), that way the add-in or macro can make changes that Excel itself will handle on a coauthoring context.
I recommend taking a look at Coauthoring in Excel add-ins of the Office Dev Center, including the linked articles inside (specifically "coauthoring", redirecting to the support center, and "About coauthoring in Excel (VBA)" at the bottom with more samples).
CanCheckOut will always return false if a workbook is open. Thus you must check before you touch it. The CheckOut command will not open the file so we must also have an open statement after CheckOut.
Using your example it would look like this;
Option Explicit
Public Sub UpdateSP()
Dim fName As String
fName = "https://organization.sharepoint.com/PathOfFile/myFile.xlsx"
If Workbooks.CanCheckOut(fName) Then
Workbooks.CheckOut fName
Dim myFile As Workbook
Set myFile = Workbooks.Open(fName)
Dim mySheet As Worksheet
Set mySheet = myFile.Sheets("Sheet1")
Dim startRange As Range
Set startRange = mySheet.Range("A" & mySheet.Rows.Count).End(xlUp).Offset(1)
startRange.Value = 9999
startRange.Offset(0, 1).Value = 0
myFile.Close SaveChanges:=True
Else
MsgBox fName & " can't be checked out at this time.", vbInformation
End If
End Sub
I've got a project where I'm reading data from an Excel worksheet and saving it in Access tables (not a direct import--see this question if you're interested). My current problem is that any time I run my "import" and then try to open the workbook in Excel, it's "locked for editing" unless/until I close Access. I don't think this should be the case. My process is
Open the workbook with Automation.
Build a collection of sheet names.
Release the Automation objects.
If there's more than one sheet, get user input on which to process.
Open an ADO recordset on a specific range & read some data.
Release the recordset & connection.
Open an ADO recordset on a different specific range & read a bunch o' data.
Release the recordset & connection.
Close the controling form.
Steps 1 - 4 and 9 live in the form file, the remainder in a module.
Am I missing something? I think I've released all the references to the workbook....
If your step #1 includes something like this:
Dim objExcel As New Excel.Application
And later releasing the object is this:
Set objExcel = Nothing
Trying including this line just before you set the object variable to Nothing:
objExcel.Quit
It also helps to make the Excel application instance visible after starting it so you're less likely to leave Excel running unseen:
objExcel.Visible = True
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
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.