Updating Powerpoint Graph 2010 from Excel 2010 - vba

I want to update Powerpoint Graph 2010 from Excel 2010.
Code looks for the Objects and finds the range with name similar in powerpoint, it applies changes to the graph. Graph format should be same only data must be updated.
Code is as follow, it is not able to find charts, either able to update it.
Option Explicit
Private Const NAMED_RANGE_PREFIX = "Export_"
Private Const NAMED_RANGE_PREFIX_TEXT = "ExportText"
Private m_sLog As String
Private Sub CommandButton1_Click()
On Error GoTo Catch
Dim pptApp As PowerPoint.Application
Dim pptPresentation As PowerPoint.Presentation
Dim pptSlide As PowerPoint.Slide
Dim pptShape As PowerPoint.Shape
Dim mgrChart As Chart
Dim mgrDatasheet As Graph.DataSheet
Dim rngData As Excel.Range
Dim iRow As Long, iCol As Long
Dim sTag As String
Dim nFound As Long, nUpdated As Long
Dim nFoundText As Long, nUpdatedText As Long
Dim i As Integer
Dim fLog As frmLog
Dim Box1Status As VbMsgBoxResult
m_sLog = ""
'Prompt to Export
Box1Status = MsgBox("Export and Save to Powerpoint Template?" & Chr(13) & "Reminder: Please use a clean template for export and be sure to back up the template beforehand. " & Chr(13) & Chr(13) & "PLEASE SAVE ANY OTHER OPEN POWERPOINT DOCUMENTS AS ALL UNSAVED WORK WILL BE LOST!", vbQuestion + vbYesNo, "Confirm Export")
If Box1Status = vbNo Then Exit Sub
i = 1
UpdateStatus "Opening Powerpoint presentation '" & Range("fileloc")
Set pptApp = New PowerPoint.Application
pptApp.Activate
Set pptPresentation = pptApp.Presentations.Open(Range("fileloc"))
pptApp.WindowState = ppWindowMinimized
'Looks for (tagged) charts to update
UpdateStatus "Searching presentation for charts..."
For Each pptSlide In pptPresentation.Slides
For Each pptShape In pptSlide.Shapes
If pptShape.Type = msoEmbeddedOLEObject Then
If TypeOf pptShape.OLEFormat.Object Is Graph.Chart Then
nFound = nFound + 1
Set mgrChart = pptShape.OLEFormat.Object
Set mgrChart = pptShape.Chart
Set mgrDatasheet = mgrChart.Application.DataSheet
With mgrDatasheet
sTag = .Cells(1, 1)
If Left(sTag, 6) = "Export" Then UpdateStatus "Found chart on slide '" & pptSlide.SlideNumber & "' with tag '" & sTag & "'. Searching Excel workbook for same tag..."
Set rngData = RangeForChart(sTag)
If rngData Is Nothing Then
' This chart has no data in this Excel workbook
If Left(sTag, 6) <> "Export" Then
UpdateStatus "Found chart on slide '" & pptSlide.SlideNumber & "' with no tag, skipping"
Else
UpdateStatus "'" & sTag & "' does not exist in workbook, skipping."
End If
Else
' Update the PowerPoint chart with the Excel data
UpdateStatus "Found '" & sTag & "' at named range '" & rngData.Name & "'. Updating presentation..."
.Cells.ClearContents
For iRow = 0 To rngData.Rows.Count - 1
For iCol = 0 To rngData.Columns.Count - 1
.Cells(iRow + 1, iCol + 1) = rngData.Cells(iRow + 1, iCol + 1)
Next iCol
Next iRow
.Application.Update
UpdateStatus "Chart with tag '" & sTag & "' updated."
nUpdated = nUpdated + 1
End If
End With
Set mgrDatasheet = Nothing
mgrChart.Application.Quit
Set mgrChart = Nothing
End If
'End If
Next pptShape
i = i + 1
Next pptSlide
UpdateStatus "Finished searching presentation. Closing PowerPoint."
pptPresentation.Save
pptPresentation.Close
Set pptPresentation = Nothing
pptApp.Quit
Set pptApp = Nothing
UpdateStatus "Done. " & nFound & " charts found and " & nUpdated & " charts updated. " & nFoundText & " text boxes found and " & nUpdatedText & " text boxes updated."
Set fLog = New frmLog
fLog.Caption = "Update of Powerpoint Template Complete"
fLog.txtLog.Text = m_sLog
fLog.Show
Unload fLog
Set fLog = Nothing
Exit Sub
Catch:
MsgBox "An unexpected error occurred while updating: " & Err.Number & " " & Err.Description, vbCritical
ForceCleanup mgrChart, mgrDatasheet, pptPresentation, pptApp
End Sub
Private Property Get RangeForChart(sTag As String) As Range
Dim sChartTag As String
Dim iUpdate As Long
Dim NameList As Range
'Dim nRow As Range
Set NameList = Range("Name_List")
If Left(sTag, 6) <> "Export" Then Exit Property
'For Each nRow In NameList.Rows
Do While sChartTag <> sTag
iUpdate = iUpdate + 1
' This will error if there is no named range for "Export_", which means that sTag does not
' exist in the workbook so return nothing
On Error Resume Next
sChartTag = ActiveWorkbook.Names(NAMED_RANGE_PREFIX & NameList(iUpdate, 1).Value).RefersToRange.Cells(1, 1)
If Err.Number <> 0 Then
' Return nothing
Exit Property
End If
On Error GoTo 0
Loop
'Next nRow
Set RangeForChart = ActiveWorkbook.Names(NAMED_RANGE_PREFIX & NameList(iUpdate, 1).Value).RefersToRange
End Property
Private Property Get RangeForText(sTag As String) As Range
Dim sTextTag As String
Dim iUpdate As Long
If Left(sTag, 10) <> "ExportText" Then Exit Property
Do While sTextTag <> sTag
iUpdate = iUpdate + 1
' This will error if there is no named range for "ExportText" & iUpdate, which means that sTag does not
' exist in the workbook so return nothing
On Error Resume Next
sTextTag = NAMED_RANGE_PREFIX_TEXT & iUpdate
If Err.Number <> 0 Then
' Return nothing
Exit Property
End If
On Error GoTo 0
Loop
Set RangeForText = ActiveWorkbook.Names(NAMED_RANGE_PREFIX_TEXT & iUpdate).RefersToRange
End Property
Private Sub UpdateStatus(sMessage As String)
m_sLog = m_sLog & Now() & ": " & sMessage & vbNewLine
Application.StatusBar = Now() & ": " & sMessage
DoEvents
End Sub
Private Sub ForceCleanup(mgrChart As Graph.Chart, mgrDatasheet As Graph.DataSheet, pptPresentation As PowerPoint.Presentation, pptApp As PowerPoint.Application)
On Error Resume Next
mgrChart.Application.Quit
Set mgrChart = Nothing
mgrDatasheet.Application.Quit
Set mgrDatasheet = Nothing
pptPresentation.Close
Set pptPresentation = Nothing
pptApp.Quit
Set pptApp = Nothing
End Sub

I don't think you need a bunch of code for this.
Build the charts in Excel, copy them, go to PowerPoint, use Paste Special - Link. Change the data in Excel, and the Excel charts update. Then open the PowerPoint presentation, and if necessary, update links.

In the data sheet for your powerpoint graph, you can "link" the cells to your excel data file by typing in one of the cells (path and file name are made up here)
=c:\PPTXfiles\excelfiles[excelfiles.xlsx]sheetname'!a1
This will create a link that doesn't show up in the links section of powerpoint, but can be updated just by opening both files and double clicking on the chart to activate it.
Sometime the paste by link feature isn't feasible to use since the end user of the file wants to "break it up" and send out parts. That is not possible without the source excel file, since the end users want to be able to edit the chart or the data.
If you can do this and then copy and paste the data sheet by values in VBA, before sending to the enduser that would be fantastic.

Bam!
Sub UpdateLinks()
Dim ExcelFile
Dim exl As Object
Set exl = CreateObject("Excel.Application")
'Open a dialog box to promt for the new source file.
ExcelFile = exl.Application.GetOpenFilename(, , "Select Excel File")
Dim i As Integer
Dim k As Integer
'Go through every slide
For i = 1 To ActivePresentation.Slides.Count
With ActivePresentation.Slides(i)
'Go through every shape on every slide
For k = 1 To .Shapes.Count
'Turn of error checking s that it doesn 't crash if the current shape doesn't already have a link
On Error Resume Next
'Set the source to be the same as teh file chosen in the opening dialog box
.Shapes(k).LinkFormat.SourceFullName = ExcelFile
If .Shapes(k).LinkFormat.SourceFullName = ExcelFile Then
'If the change was successful then also set it to update automatically
.Shapes(k).LinkFormat.Update
End If
On Error GoTo 0
Next k
End With
Next i
End Sub

Related

Export all charts in an Excel-workbook to a windows folder

I tried to run the following macro. Seems to work (I don`t have any error) but in the end only an empty folder opens (no picture exported). Please, help me with any advice! I am a beginner in VBA. Thank you very much!
Sub ExportAllCharts()
Dim objShell As Object
Dim objWindowsFolder As Object
Dim strWindowsFolder As String
Dim objSheet As Excel.Worksheet
Dim objChartObject As Excel.ChartObject
Dim objChart As Excel.Chart
'Select a Windows folder
Set objShell = CreateObject("Shell.Application")
Set objWindowsFolder = objShell.BrowseForFolder(0, "Select a Windows folder:", 0, "")
If Not objWindowsFolder Is Nothing Then
strWindowsFolder = objWindowsFolder.self.Path & "\"
For i = ThisWorkbook.Worksheets.Count To 1 Step -1
Set objSheet = ThisWorkbook.Worksheets(i)
If objSheet.ChartObjects.Count > 0 Then
For Each objChartObject In objSheet.ChartObjects
Set objChart = objChartObject.Chart
objChart.Export strWindowsFolder & objChart.Name & ".png"
Next
End If
Next
'Open the windows folder
Shell "Explorer.exe" & " " & strWindowsFolder, vbNormalFocus
End If
End Sub
Source code link
Now I`m trying to find a solution to export all the charts with the worksheet name + a suffix.
I wish I could insert the desired suffix (the same for all worksheets) into a pop-up window.
I have this code that renames all the worksheets, but I need to adapt it to rename them only partially. I thought maybe I could incorporate it into the initial macro.
Sub ChangeWorkSheetName()
Dim Rng As Range
Dim WorkRng As Range
On Error Resume Next
xTitleId = "Write the new Worksheets Name"
NewName = Application.InputBox("Name", xTitleId, "", Type:=2)
j = 1
For i = 1 To Application.Sheets.Count
If Application.Sheets(i).Visible Then
Application.Sheets(i).Name = NewName & j
j = j + 1
End If
Next
End Sub
Can anyone give me a suggestion? Thank you very much!
If you need to include charts on chart sheets you need a second loop:
Sub ExportAllCharts()
Dim objShell As Object
Dim objWindowsFolder As Object
Dim strWindowsFolder As String
Dim objSheet As Excel.Worksheet
Dim objChartObject As Excel.ChartObject
Dim objChart As Excel.Chart
'Select a Windows folder
Set objShell = CreateObject("Shell.Application")
Set objWindowsFolder = objShell.BrowseForFolder(0, "Select a Windows folder:", 0, "")
If Not objWindowsFolder Is Nothing Then
strWindowsFolder = objWindowsFolder.self.Path & "\"
'charts on chart sheets
For Each objChart In ThisWorkbook.Charts
objChart.Export strWindowsFolder & objChart.Name & ".png"
Next objChart
'chartobjects (on worksheets)
For Each objSheet In ThisWorkbook.Worksheets
For Each objChartObject In objSheet.ChartObjects
With objChartObject.Chart
.Export strWindowsFolder & .Name & ".png"
End With
Next
Next
'Open the windows folder
Shell "Explorer.exe" & " " & strWindowsFolder, vbNormalFocus
End If
End Sub

Looking to Loop Excel VBA Macro through Multiple Worksheets?

Looking to loop the following code through (about) 125 worksheets in an Excel workbook and pull the listed cell values into one database entry log on the 'Database' worksheet'. Right now it is only pulling from one of the tabs . (PO VT-0189). Wondering how to correct.
Private Sub PopulateOrderInfo()
Dim OrderDate As String, PONumber As String, Vendor As String, ShipTo As String, SKU As String
Dim R As Long, LastSKURow As Long, NextDBRow As Long, OFrm As Worksheet, DB As Worksheet
For Each OFrm In ActiveWorkbook.Worksheets
Set OFrm = Worksheets("PO VT-0189")
Set DB = Worksheets("Database")
OrderDate = OFrm.Range("N4")
PONumber = OFrm.Range("N3")
Vendor = OFrm.Range("A13")
ShipTo = OFrm.Range("I13")
POTotal = OFrm.Range("P43")
LastSKURow = OFrm.Range("A38").End(xlUp).Row
For R = 21 To LastSKURow
SKU = OFrm.Range("A" & R).Value
SKUDesc = OFrm.Range("D" & R).Value
SKUQty = OFrm.Range("K" & R).Value
Lntotal = OFrm.Range("M" & R).Value
NextDBRow = DB.Cells(DB.Rows.Count, "A").End(xlUp).Row + 1
DB.Range("A" & NextDBRow).Value = OrderDate
DB.Range("B" & NextDBRow).Value = PONumber
DB.Range("C" & NextDBRow).Value = Vendor
DB.Range("D" & NextDBRow).Value = ShipTo
DB.Range("E" & NextDBRow).Value = SKU
DB.Range("F" & NextDBRow).Value = SKUDesc
DB.Range("G" & NextDBRow).Value = SKUQty
DB.Range("H" & NextDBRow).Value = Lntotal
DB.Range("I" & NextDBRow).Value = POTotal
Next R
Next OFrm
End Sub
I think you can also shorten your code by avoiding the loop and most of the variables seem unnecessary to me.
Private Sub PopulateOrderInfo()
Dim R As Long, LastSKURow As Long, NextDBRow As Long, OFrm As Worksheet, DB As Worksheet
Set DB = Worksheets("Database")
For Each OFrm In ActiveWorkbook.Worksheets
If OFrm.Name <> DB.Name Then
LastSKURow = OFrm.Range("A38").End(xlUp).Row
R = LastSKURow - 21 + 1
NextDBRow = DB.Cells(DB.Rows.Count, "A").End(xlUp).Row + 1
DB.Range("A" & NextDBRow).Resize(R).Value = OFrm.Range("N4")
DB.Range("B" & NextDBRow).Resize(R).Value = OFrm.Range("N3")
DB.Range("C" & NextDBRow).Resize(R).Value = OFrm.Range("A13")
DB.Range("D" & NextDBRow).Resize(R).Value = OFrm.Range("I13")
DB.Range("E" & NextDBRow).Resize(R).Value = OFrm.Range("A21").Resize(R).Value
DB.Range("F" & NextDBRow).Resize(R).Value = OFrm.Range("D21").Resize(R).Value
DB.Range("G" & NextDBRow).Resize(R).Value = OFrm.Range("K21").Resize(R).Value
DB.Range("H" & NextDBRow).Resize(R).Value = OFrm.Range("M21").Resize(R).Value
DB.Range("I" & NextDBRow).Resize(R).Value = OFrm.Range("P43")
End If
Next OFrm
End Sub
Use a for loop and WorkSheets collection like:
For I = 1 to worksheets.count
if worksheets(i).name <> "Database" then
Add your code here
end if
Next i
This loops through every worksheet in your workbook and does what ever you need to all worksheets except the Database.
Using a for each... loop
For Each ws In wb.Worksheets
If ws.name = "Database" Then
'Leave blank to just skip database. Code here if you want something special on database. OR statements can be used to exclude additional sheets
Else
'Code here
End If
Next
I think you described the issue fairly well. Just to confirm, you want to loop through all worksheets in one single workbook, right. Try the script below. Feedback if you have additional questions, concerns, etc. Thanks.
Sub ImportAll()
Dim blnHasFieldNames As Boolean, blnEXCEL As Boolean, blnReadOnly As Boolean
Dim lngCount As Long
Dim objExcel As Object, objWorkbook As Object
Dim colWorksheets As Collection
Dim strPathFile as String, strTable as String
Dim strPassword As String
' Establish an EXCEL application object
On Error Resume Next
Set objExcel = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Set objExcel = CreateObject("Excel.Application")
blnEXCEL = True
End If
Err.Clear
On Error GoTo 0
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = False
' Replace C:\Filename.xls with the actual path and filename
strPathFile = "C:\Filename.xls"
' Replace tablename with the real name of the table into which
' the data are to be imported
strTable = "tablename"
' Replace passwordtext with the real password;
' if there is no password, replace it with vbNullString constant
' (e.g., strPassword = vbNullString)
strPassword = "passwordtext"
blnReadOnly = True ' open EXCEL file in read-only mode
' Open the EXCEL file and read the worksheet names into a collection
Set colWorksheets = New Collection
Set objWorkbook = objExcel.Workbooks.Open(strPathFile, , blnReadOnly, , _
strPassword)
For lngCount = 1 To objWorkbook.Worksheets.Count
colWorksheets.Add objWorkbook.Worksheets(lngCount).Name
Next lngCount
' Close the EXCEL file without saving the file, and clean up the EXCEL objects
objWorkbook.Close False
Set objWorkbook = Nothing
If blnEXCEL = True Then objExcel.Quit
Set objExcel = Nothing
' Import the data from each worksheet into the table
For lngCount = colWorksheets.Count To 1 Step -1
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, _
strTable, strPathFile, blnHasFieldNames, colWorksheets(lngCount) & "$"
Next lngCount
' Delete the collection
Set colWorksheets = Nothing
' Uncomment out the next code step if you want to delete the
' EXCEL file after it's been imported
' Kill strPathFile
End Sub

Embedding Several Images into an Email using VBA from Excel to Outlook and using CID

I'm trying to embed several graphs (as PNGs) from a Excel VBA Macro to Outlook.
The images embed however, it's not all 8 images but the first one repeated 8 times.
Sub Test()
Dim sheetNumber, size, i As Integer
Dim chartNames(), FNames() As String
Dim objChrt As ChartObject
Dim myChart As Chart
'Activate Charts Sheet
Sheets("GRAFICAS").Activate
'Calculate Number of Charts in Sheet
chartNumber = ActiveSheet.ChartObjects.Count
'Redimension Arrays to fit all Chart Export Names
ReDim chartNames(chartNumber)
ReDim FNames(chartNumber)
'Loops through all the charts in the GRAFICAS sheet
For i = 1 To chartNumber
'Select chart with index i
Set objChrt = ActiveSheet.ChartObjects(i)
Set myChart = objChrt.Chart
'Generate a name for the chart
chartNames(i) = "myChart" & i & ".png"
On Error Resume Next
Kill ThisWorkbook.Path & "\" & chartNames(i)
On Error GoTo 0
'Export Chart
myChart.Export Filename:=Environ$("TEMP") & "\" & chartNames(i), Filtername:="PNG"
'Save path to exported chart
FNames(i) = Environ$("TEMP") & "\" & chartNames(i)
Next i
'Declare the Object variables for Outlook.
Dim objOutlook As Object
'Verify Outlook is open.
On Error Resume Next
Set objOutlook = GetObject(, "Outlook.Application")
'If Outlook is not open, end the Sub.
If objOutlook Is Nothing Then
Err.Clear
MsgBox _
"Cannot continue, Outlook is not open.", , _
"Please open Outlook and try again."
Exit Sub
'Outlook is determined to be open, so OK to proceed.
Else
'Establish an Object variable for a mailitem.
Dim objMailItem As Object
Set objMailItem = objOutlook.CreateItem(0)
'Build the mailitem.
Dim NewBody As String
On Error Resume Next
With objMailItem
.To = "dummy#test.com"
.Subject = "Testing Lesson 31 email code"
.Importance = 1 'Sets it as Normal importance (Low = 0 and High = 2)
'Change the Display command to Send without reviewing the email.
' .Display
End With
For i = 1 To chartNumber
objMailItem.Attachments.Add FNames(i)
'Put together the HTML to embed
NewBody = NewBody + HTMLcode & "<div align=center>" & "<IMG src=cid: myChart" & i & ".png></img>" & "</div>"
Next
MsgBox NewBody
'Set the HTML body
objMailItem.HTMLBody = NewBody
'Display email before sending
objMailItem.Display
'Close the If block.
End If
Kill Fname
End Sub
MsgBox NewBody outputs:
and the final email looks like:
It should show all charts one below the other one, however it only takes myChart1.png and repeats it 8 times, despite the output of NewBody.
What am I doing wrong? I'm using Outlook 2013 and Excel 2013
UPDATE: I added another image and it seems to, in this case, repeat the last image I added 9 times (same as number of attached images). I'm guessing it's a problem with the cid, maybe ids aren't unique?
You must set the PR_ATTACH_CONTENT_ID property on the attachment appropriately to match the value of the cid attribute:
Set attach = objMailItem.Attachments.Add(FNames(i))
'Put together the HTML to embed
Dim cid
cid = "myChart" & i & ".png"
NewBody = NewBody + HTMLcode & "<div align=center>" & "<IMG src=cid:" & cid & "</img>" & "</div><br><br>"
Call attach.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", cid)

Excel VBA compare two workbooks write difference to text file

After much struggle with syntax, I have following code working, but I want to use error checking to determine if file is already open using a string.
(Disclosure: I have copied comparesheets from source that I will link when I find it)
Trying to replace this code
Set wbkA = Workbooks.Open(FileName:=wba)
with
Set wBook = Workbooks(wba) 'run time error subscript out of range
If wBook Is Nothing Then
Set wbkA = Workbooks.Open(FileName:=wba)
End If
But I have syntax problem with the string wba. What is proper way use string here?
Sub RunCompare_WS2()
Dim i As Integer
Dim wba, wbb As String
Dim FileName As Variant
Dim wkbA As Workbook
Dim wkbB As Workbook
Dim wBook As Workbook
wba = "C:\c.xlsm"
wbb = "C:\d.xlsm"
'Set wBook = Workbooks(FileName:=wba) 'compiler error named argument not found
'Set wBook = Workbooks(wba) 'run time error subscript out of range
'If wBook Is Nothing Then
'Set wbkA = Workbooks.Open(FileName:=wba)
'End If
Set wbkA = Workbooks.Open(FileName:=wba)
Set wbkB = Workbooks.Open(FileName:=wbb)
For i = 1 To Application.Sheets.Count
Call compareSheets(wbkA.Sheets(i), wbkB.Sheets(i))
Next i
wbkA.Close SaveChanges:=True
wbkB.Close SaveChanges:=False
MsgBox "Completed...", vbInformation
End Sub
Sub compareSheets(shtSheet1 As Worksheet, shtSheet2 As Worksheet)
Dim mycell As Range
Dim mydiffs As Integer
Dim DifFound As Boolean
DifFound = False
sDestFile = "C:\comp-wb.txt"
DestFileNum = FreeFile()
Open sDestFile For Append As DestFileNum
'For each cell in sheet2 that is not the same in Sheet1, color it lightgreen in first file
For Each mycell In shtSheet1.UsedRange
If Not mycell.Value = shtSheet2.Cells(mycell.Row, mycell.Column).Value Then
If DifFound = False Then
Print #DestFileNum, "Row,Col" & vbTab & vbTab & "A Value" & vbTab & vbTab & "B Value"
DifFound = True
End If
mycell.Interior.Color = 5296274 'LightGreen
Print #DestFileNum, mycell.Row & "," & mycell.Column, mycell.Value, shtSheet2.Cells(mycell.Row, mycell.Column).Value '& vbInformation
mydiffs = mydiffs + 1
End If
Next
Print #DestFileNum, mydiffs & " differences found in " & shtSheet1.Name
Close #DestFileNum
End Sub
You can use On Error Resume Next to ignore any error:
Const d As String = "C:\"
wba = "c.xlsm"
On Error Resume Next
Set wBook = Workbooks(wba)
On Error Goto 0
If wBook Is Nothing Then
Set wbkA = Workbooks.Open(d & wba) 'join string d & wba
End If
This will check to see if you have the file open.
Option Explicit
Function InputOpenChecker(InputFilePath) As Boolean
Dim WB As Workbook
Dim StrFileName As String
Dim GetFileName As String
Dim IsFileOpen As Boolean
InputOpenChecker = False
'Set Full path and name of file to check if already opened.
GetFileName = Dir(InputFilePath)
StrFileName = InputFilePath & GetFileName
IsFileOpen = False
For Each WB In Application.Workbooks
If WB.Name = GetFileName Then
IsFileOpen = True
Exit For
End If
Next WB
If you dont have it open, check to see if someone else does.
On Error Resume Next
' If the file is already opened by another process,
' and the specified type of access is not allowed,
' the Open operation fails and an error occurs.
Open StrFileName For Binary Access Read Write Lock Read Write As #1
Close #1
' If an error occurs, the document is currently open.
If Err.Number <> 0 Then
'Set the FileLocked Boolean value to true
FileLocked = True
Err.Clear
End If
And one reason for your error could be the inclusion of "FileName:=" in the Workbooks.Open. Try;
Set wbkA = Workbooks.Open(wba)
Set wbkB = Workbooks.Open(wbb)
Fixed my code and reposting with corrections for clarity.
Note I moved to C:\temp since writing to root C:\ folder should not be used because many work computers have root folder locked for security as my colleague just found out!
Sub RunCompare_WS9() 'compare two WKbooks, all sheets write diff to text file
Dim i As Integer
Dim wba, wbb As String
Dim FileName As Variant
Dim wkbA As Workbook
Dim wkbB As Workbook
Dim wbook1 As Workbook
Dim wbook2 As Workbook
wba = "C:\test\c.xlsm"
wbb = "C:\test\d.xlsm"
On Error Resume Next
Set wbook1 = Workbooks(wba)
On Error GoTo 0
If wbook1 Is Nothing Then
Set wbkA = Workbooks.Open(wba)
End If
On Error Resume Next
Set wbook2 = Workbooks(wbb)
On Error GoTo 0
If wbook2 Is Nothing Then
Set wbkB = Workbooks.Open(wbb)
End If
For i = 1 To Application.Sheets.Count
Call compareSheets(wbkA.Sheets(i), wbkB.Sheets(i))
Next i
wbkA.Close SaveChanges:=True
wbkB.Close SaveChanges:=False
MsgBox "Completed...", vbInformation
End Sub
Sub compareSheets(shtSheet1 As Worksheet, shtSheet2 As Worksheet)
Dim mycell As Range
Dim mydiffs As Integer
Dim DifFound As Boolean
DifFound = False
sDestFile = "C:\Test\comp2-wb.txt"
DestFileNum = FreeFile()
Open sDestFile For Append As DestFileNum
'For each cell in sheet2 that is not the same in Sheet1, color it lightgreen in first file
For Each mycell In shtSheet1.UsedRange
If Not mycell.Value = shtSheet2.Cells(mycell.Row, mycell.Column).Value Then
If DifFound = False Then
Print #DestFileNum, "Row,Col" & vbTab & vbTab & "A Value" & vbTab & vbTab & "B Value"
DifFound = True
End If
mycell.Interior.Color = 5296274 'LightGreen
Print #DestFileNum, mycell.Row & "," & mycell.Column, mycell.Value, shtSheet2.Cells(mycell.Row, mycell.Column).Value '& vbInformation
mydiffs = mydiffs + 1
End If
Next
Print #DestFileNum, mydiffs & " differences found in " & shtSheet1.Name
Close #DestFileNum
End Sub

Add new sheet to existing Excel workbook with VB code

This code creates an Excel file with one sheet. This sheet contains the code of an item like (ASR/Floor/Dept./Item_Name/Item_details/1) which I created and works fine, but I want to add a sheet into this Excel file to create another item code, and then save this file.
Dim xlApp As Excel.Application
Dim wb As Workbook
Dim ws As Worksheet
Dim var As Variant
Dim code As String
Dim i, nocode As Integer
Dim fname, heading As String
code = "ASR/" & Text1.Text & "/" & Text2.Text & "/" & Text3.Text & "/" & Text4.Text
Set xlApp = New Excel.Application
Set wb = xlApp.Workbooks.Add ' Create a new WorkBook
Set ws = wb.Worksheets("Sheet1") 'Specify your worksheet name
nocode = txtnocode.Text
heading = Text6.Text
For i = 2 To nocode + 1
ws.Cells(i, 1).Value = code & "/" & i - 1 '"ORG"
Next i
fname = "c:\" & Text5.Text & ".xls"
wb.SaveAs (fname)
wb.Close
xlApp.Quit
Set ws = Nothing
Set wb = Nothing
Set xlApp = Nothing
The Worksheets.Add method is what you are looking for:
wb.WorkSheets.Add().Name = "SecondSheet"
See MSDN(scroll down and expand Sheets and Worksheets) for the different parameters you can give to .Add including being able to add the sheet before or after a specific one.
Set ws = wb.Sheets("Sheet1")
Set ws = wb.Sheets.Add
ws.Activate
This is some standard code I use for this type of problem
Note: This code is VBA, to run from within the Excel document itself
Option Explicit
Private m_sNameOfOutPutWorkSheet_1 As String
Sub Delete_Recreate_TheWorkSheet()
On Error GoTo ErrorHandler
'=========================
Dim strInFrontOfSheetName As String
m_sNameOfOutPutWorkSheet_1 = "Dashboard_1"
strInFrontOfSheetName = "CONTROL" 'create the new worksheet in front of this sheet
'1] Clean up old data if it is still there
GetRidOf_WorkSheet_IfItExists (m_sNameOfOutPutWorkSheet_1)
CreateNewOutputWorkSheet m_sNameOfOutPutWorkSheet_1, strInFrontOfSheetName
'Color the tab of the new worksheet
ActiveWorkbook.Sheets(m_sNameOfOutPutWorkSheet_1).Tab.ColorIndex = 5
'Select the worksheet that I started with
Worksheets(strInFrontOfSheetName).Select
'=========================
Exit Sub
ErrorHandler:
Select Case Err.Number
Case Else
MsgBox "One_Main - Error: " & Err.Number & " " & Err.Description
End Select
End Sub
Sub GetRidOf_WorkSheet_IfItExists(sWorkSheetName_ForInitalData As String)
On Error GoTo ErrorHandler
'=========================
If fn_WorkSheetExists(sWorkSheetName_ForInitalData) Then
'Sheet Exists
Application.DisplayAlerts = False
Worksheets(sWorkSheetName_ForInitalData).Delete
Application.DisplayAlerts = True
End If
'=========================
Exit Sub
ErrorHandler:
Select Case Err.Number
Case Else
MsgBox "GetRidOf_WorkSheet_IfItExists - Error: " & Err.Number & " " & Err.Description
End Select
End Sub
Function fn_WorkSheetExists(wsName As String) As Boolean
On Error Resume Next
fn_WorkSheetExists = Worksheets(wsName).Name = wsName
End Function
Sub CreateNewOutputWorkSheet(sWorkSheetName_ForOutputData As String, strInFrontOfSheetName As String)
On Error GoTo ErrorHandler
'=========================
If fn_WorkSheetExists(sWorkSheetName_ForOutputData) Then
'Sheet Exists
Application.DisplayAlerts = False
Worksheets(sWorkSheetName_ForOutputData).Delete
Application.DisplayAlerts = True
End If
Dim wsX As Worksheet
Set wsX = Sheets.Add(Before:=Worksheets(strInFrontOfSheetName))
wsX.Name = sWorkSheetName_ForOutputData
'=========================
Exit Sub
ErrorHandler:
Select Case Err.Number
Case Else
MsgBox "CreateNewOutputWorkSheet - Error: " & Err.Number & " " & Err.Description
End Select
End Sub