I was looking for code to determine the difference between two selected cells and display it in the status bar of Excel 2010.
I found some code, but it applies only to the workbook that contains that code.
Is it possible to make this code functional on every workbook I am working with?
It would be great if this kind of code runs automatically like macros from personal.xlsb.
Public Sub workbook_SheetSelectionChange(ByVal sh As Object, ByVal Target As Range)
Set sh = ActiveSheet
If Selection.Cells.Count = 2 Then
On Error Resume Next
If WorksheetFunction.Count(Range(Selection.Address)) = 2 Then
Application.StatusBar = "The difference is " & _
WorksheetFunction.Max(Range(Selection.Address)) _
- WorksheetFunction.Min(Range(Selection.Address))
Else
Application.StatusBar = "The difference is " & _
WorksheetFunction.Max(Range(Selection.Address))
End If
Else
Application.StatusBar = False
End If
End Sub
I found some code, but it applies only to the workbook that contains that code. Is it possible to make this code functional on every workbook I am working with?
You will have to create an Add-In for this. And then place this in your Add-In's ThisWorkbook module. After the Add-In has been created, activate it by checking its check-box on the Developer Tab, Add-Ins Section.
Private WithEvents oXLApp As Excel.Application
Private Sub Workbook_Open()
Set oXLApp = Excel.Application
End Sub
Private Sub oXLApp_SheetSelectionChange(ByVal Sh As Object, _
ByVal Target As Range)
'
'~~> Rest of the code here
'
End Sub
These question resulted in the following tool.
Save the following project as .xla
Thisworkbook:
Private WithEvents oXLApp As Excel.Application
Private Sub Workbook_Open()
Set oXLApp = Excel.Application
End Sub
Private Sub oXLApp_SheetSelectionChange(ByVal Sh As Object, ByVal Target As range)
Dim limit As Long
limit = 300000 ' selection limit
Dim frmt As String
frmt = "#,##0;(#,##0);""-""" ' formating at status bar
' first condition - one selection area
If Selection.Areas.Count = 1 Then
On Error Resume Next
If Selection.Cells.Count > 1 And Selection.Cells.Count < limit Then
On Error Resume Next
Application.StatusBar = _
" D: " & Format(WorksheetFunction.Max(Selection) - WorksheetFunction.Min(Selection), frmt) & _
" U: " & Format(Unique(Selection), frmt) & _
" 2X: " & Format(WorksheetFunction.Sum(Selection) * 2, frmt) & _
" X2: " & Format(WorksheetFunction.Sum(Selection) / 2, frmt) & _
" NC: " & Format(WorksheetFunction.CountIf(Selection, "<0"), frmt) & _
" NS: " & Format(WorksheetFunction.SumIf(Selection, "<0"), frmt)
Else
If Selection.Cells.Count = 1 Or Selection.Cells.Count >= limit Then
On Error Resume Next
Application.StatusBar = False
End If ' No condition
End If ' Cells > 2 and < limit
End If ' Areas = 1 - end of first condition
' second condition - more than one selection areas
If Selection.Areas.Count > 1 Then
Dim r1 As range
Dim r2 As range
Set r1 = Selection.Areas(1)
'WorksheetFunction.Sum (r1)
On Error Resume Next
Set r2 = Selection.Areas(2)
'Set multipleRange = Union(r1, r2)
On Error Resume Next
If Selection.Cells.Count > 1 And Selection.Cells.Count < limit Then
On Error Resume Next
Application.StatusBar = _
" D: " & Format(DIFF(r1, r2), frmt) & _
" U: " & Format(Unique(r1), frmt) & _
" 2X: " & Format(WorksheetFunction.Sum(r1) * 2, frmt) & _
" X2: " & Format(WorksheetFunction.Sum(r1) / 2, frmt) & _
" NC: " & Format(WorksheetFunction.CountIf(r1, "<0"), frmt) & _
" NS: " & Format(WorksheetFunction.SumIf(r1, "<0"), frmt)
Else
If Selection.Cells.Count = 1 Or Selection.Cells.Count >= limit Then
On Error Resume Next
Application.StatusBar = False
End If ' no condition
End If ' Cells > 1
End If ' Areas > 1 - end of second condition
End Sub
Module 1:
Public Function DIFF(rng1 As range, rng2 As range)
DIFF = WorksheetFunction.Sum(rng1) - WorksheetFunction.Sum(rng2)
End Function
Module 2:
Public Function Unique(ByRef rngToCheck As range) As Variant
Dim colDistinct As Collection
Dim varValues As Variant, varValue As Variant
Dim lngCount As Long, lngRow As Long, lngCol As Long
On Error GoTo ErrorHandler
varValues = rngToCheck.Value
'if rngToCheck is more than 1 cell then
'varValues will be a 2 dimensional array
If IsArray(varValues) Then
Set colDistinct = New Collection
For lngRow = LBound(varValues, 1) To UBound(varValues, 1)
For lngCol = LBound(varValues, 2) To UBound(varValues, 2)
varValue = varValues(lngRow, lngCol)
'ignore blank cells and throw error
'if cell contains an error value
If LenB(varValue) > 0 Then
'if the item already exists then an error will
'be thrown which we want to ignore
On Error Resume Next
colDistinct.Add vbNullString, CStr(varValue)
On Error GoTo ErrorHandler
End If
Next lngCol
Next lngRow
lngCount = colDistinct.Count
Else
If LenB(varValues) > 0 Then
lngCount = 1
End If
End If
Unique = lngCount
Exit Function
ErrorHandler:
Unique = CVErr(xlErrValue)
End Function
Related
I have 3 workbook web queries on a single data sheet , and I have a dropdown object with a list of months in the year (1-12). My idea for the automation was to have the query formula update based on the user selection of the dropdown value and update the query formula accordingly and refresh.
The VBA code works fine, but I get this message for one of the queries.
The reason is that the query (ex when changed from month 2 to month 3), has 2 more lines and is not the exact table height.
Any ideas how to debug this / circumvent this message. Code below:
Sub DropDown9_Change()
Dim wbconn As WorkbookConnection, qT As QueryTable
Dim wB As Workbook, wS As Worksheet
'For Each wbconn In ThisWorkbook.Connections
'Debug.Print wbconn.Name & " - " & wbconn.OLEDBConnection.CommandText & " - " & _
'wbconn.OLEDBConnection.SourceDataFile
''wbconn.Refresh
'Next wbconn
Set wB = Workbooks("OH Burdening Template.xlsb")
If ShData.Shapes("Drop Down 9").ControlFormat.Value > _
ShCalendar.Range("B3").Value Then
MsgBox "Cannot be based on future periods!", vbExclamation
Else
'Refresh WB queries
Call Refresh_Queries(ShData.Shapes("Drop Down 9").ControlFormat.Value, wB, ShData)
End If
ShData.Columns.AutoFit
End Sub
Private Function Refresh_Queries(ByVal Period As Integer, ByVal wB As Workbook, _
ByVal thisSheet As Worksheet)
With Application
.StatusBar = "Now refreshing queries on :" & ShData.Name
.ScreenUpdating = False
.EnableEvents = False
End With
Dim I As Integer, LObj As ListObject
Dim strL As Integer, str As String
Dim Pos As Integer
Dim F As String
Dim startPos As Integer
str = "?year=2018&period="
strL = Len(str)
For I = 1 To wB.Queries.Count
On Error GoTo view_err
F = wB.Queries(I).Formula
Pos = VBA.InStr(1, F, str, vbBinaryCompare)
startPos = Pos + strL
'Debug.Print F
'Replacing the period part of the string with the period entered in the dropdown
F = WorksheetFunction.Replace(F, startPos, 1, Period)
wB.Queries.Item(I).Formula = F
'Debug.Print Mid(F, startPos, 1)
Next I
For Each LObj In thisSheet.ListObjects
Application.StatusBar = "Refreshing " & LObj.Name
LObj.QueryTable.Refresh False
Debug.Print LObj.Name & Chr(32) & "Refreshed successfully!"
Next LObj
With Application
.StatusBar = False
.ScreenUpdating = True
.EnableEvents = True
End With
Set LObj = Nothing
Exit Function
view_err:
Debug.Print LObj.Name & Chr(32) & "Refresh Failed!"
MsgBox Err.Description & " (" & Err.Number & ")", vbExclamation
With Application
.StatusBar = False
.ScreenUpdating = True
.EnableEvents = True
End With
End Function
This may be similar to this question but I believe it goes a step further in complexity which is why I asked it.
Context: I'm building a budget spreadsheet that can create and delete rows from tables. In the sheet I have two tables. One contains totals based on category, while the other table contains the transactions the user can enter in to populate the totals in the other table. I protected the worksheet to keep users from breaking the formulas and only have the cells they should edit (i.e. input values in) unprotected. I also have macros to insert and delete one or multiple rows on a table (I coded the macros to unprotect/protect the worksheet before and after the macro is finished running).
Problem: My question deals with the first table. In that table, I want to ensure that the "Deposits" row cannot be deleted. Question is, in my code, how can I ensure the user can delete all other rows in another table that contains "Deposits" while preventing deletion of the "Deposits" row in this table? I'm thinking of the following pseudo code, but feel free to make other suggestions:
'If selected range contains cells in Column A
'and cell in selected range = Deposits
'Then pop error message
'Exit Sub
And here is the code I have for my delete macro
Sub DeleteRow()
'
' DeleteRow Macro
'
' Keyboard Shortcut: Ctrl+Shift+D
'
Dim loTtest As ListObject
Dim loSet As ListObject
Dim c As Range
Dim arrRows() As Variant
Dim arrTemp() As Variant
Dim xFind As Variant
Dim iCnt As Long
Dim sMsg As String
ActiveSheet.Unprotect Password:="PYS"
Erase arrRows()
iCnt = 1
For Each c In Selection.Cells
If Not c.ListObject Is Nothing Then
If loSet Is Nothing Then
Set loSet = c.ListObject
Else
If c.ListObject <> loSet Then
'different table
MsgBox "You have more than one table selected.", vbInformation, "ERROR!"
ActiveSheet.Protect Password:="PYS"
GoTo MyExit
End If
End If
If iCnt = 1 Then
ReDim arrRows(1 To iCnt)
arrRows(iCnt) = c.Row - loSet.HeaderRowRange.Row
iCnt = iCnt + 1
Else
On Error Resume Next
xFind = 0
xFind = WorksheetFunction.Match(c.Row - loSet.HeaderRowRange.Row, arrRows(), 0)
If xFind = 0 Then
ReDim Preserve arrRows(1 To iCnt)
arrRows(iCnt) = c.Row - loSet.HeaderRowRange.Row
iCnt = iCnt + 1
End If
Err.Clear
On Error GoTo 0
End If
Else
'a cell is not in a table
MsgBox "Your selection is all or partially outside of a table.", vbInformation, "ERROR!"
ActiveSheet.Protect Password:="PYS"
GoTo MyExit
End If
Next c
Call SortArray(arrRows())
sMsg = "Are you sure you want to delete " & UBound(arrRows) & " rows from from this table?"
If MsgBox(sMsg, vbYesNo + vbDefaultButton2, "CONTINUE?") <> vbYes Then
ActiveSheet.Protect Password:="PYS"
Exit Sub
End If
For iCnt = UBound(arrRows) To LBound(arrRows) Step -1
loSet.ListRows(arrRows(iCnt)).Delete
Next iCnt
ActiveSheet.Protect Password:="PYS"
Exit Sub
MyExit:
End Sub
Sub SortArray(MyArray() As Variant)
Dim iStart As Long
Dim iEnd As Long
Dim iStep As Long
Dim iMove As Long
Dim vTemp As Variant
iStart = LBound(MyArray)
iEnd = UBound(MyArray)
For iStep = iStart To iEnd - 1
For iMove = iStep + 1 To iEnd
If MyArray(iStep) > MyArray(iMove) Then
vTemp = MyArray(iMove)
MyArray(iMove) = MyArray(iStep)
MyArray(iStep) = vTemp
End If
Next iMove
Next iStep
End Sub
By the way, I didn't come up with all of this myself; I piecemealed most of this code. :) Let me know if you need any more info or context. Thanks in advance!
Here is the link to the budget workbook.
If ActiveSheet.Cells(c.Row, 1).Value = "Deposits" ThenHere is the working DeleteRow sub
Sub DeleteRow()
'
' DeleteRow Macro
'
' Keyboard Shortcut: Ctrl+Shift+D
'
Dim loTtest As ListObject
Dim loSet As ListObject
Dim c As Range
Dim arrRows() As Variant
Dim arrTemp() As Variant
Dim xFind As Variant
Dim iCnt As Long
Dim sMsg As String
ActiveSheet.Unprotect Password:="PYS"
Erase arrRows()
iCnt = 1
'This is the loop that I added before anything else to keep people from deleting the row with "Deposits"
For Each c In Selection.Cells
If ActiveSheet.Cells(c.Row, 1).Value = "Deposits" Then
MsgBox "Your Selection contains 'Deposits'!" & vbCrLf & _
"The 'Deposits' row cannot be deleted!", vbExclamation
GoTo MyExit
End If
Next
For Each c In Selection.Cells
If Not c.ListObject Is Nothing Then
If loSet Is Nothing Then
Set loSet = c.ListObject
Else
If c.ListObject <> loSet Then
'different table
MsgBox "You have more than one table selected.", vbInformation, "ERROR!"
ActiveSheet.Protect Password:="PYS"
GoTo MyExit
End If
End If
If iCnt = 1 Then
ReDim arrRows(1 To iCnt)
arrRows(iCnt) = c.Row - loSet.HeaderRowRange.Row
iCnt = iCnt + 1
Else
On Error Resume Next
xFind = 0
xFind = WorksheetFunction.Match(c.Row - loSet.HeaderRowRange.Row, arrRows(), 0)
If xFind = 0 Then
ReDim Preserve arrRows(1 To iCnt)
arrRows(iCnt) = c.Row - loSet.HeaderRowRange.Row
iCnt = iCnt + 1
End If
Err.Clear
On Error GoTo 0
End If
Else
'a cell is not in a table
MsgBox "Your selection is all or partially outside of a table.", vbInformation, "ERROR!"
ActiveSheet.Protect Password:="PYS"
GoTo MyExit
End If
Next c
Call SortArray(arrRows())
sMsg = "Are you sure you want to delete " & UBound(arrRows) & " rows from from this table?"
If MsgBox(sMsg, vbYesNo + vbDefaultButton2, "CONTINUE?") <> vbYes Then
ActiveSheet.Protect Password:="PYS"
Exit Sub
End If
For iCnt = UBound(arrRows) To LBound(arrRows) Step -1
loSet.ListRows(arrRows(iCnt)).Delete
Next iCnt
ActiveSheet.Protect Password:="PYS"
Exit Sub
MyExit:
End Sub
I have an Excel-Workbook. In this workbook a new sheet is created via VBA.
The more sheets this workbook has the more confusing is it, because I have to scroll a long time to reach any sheet in the middle.
I want to create an overview-sheet
in which the names of the sheets are listed AND
the name of the sheets have to be hyperlinks.
My code doesn't work at all -
BTW, I have to work with Excel 2003
Here's what I have:
Sub GetHyperlinks()
Dim ws As Worksheet
Dim i As Integer
i = 4
ActiveWorkbook.Sheets("overview").Cells(i, 1).Select
For Each ws In Worksheets
ActiveWorkbook.Sheets("overwies").Hyperlinks.Add _
Ancor:=Selection, _
Address:="", _
SubAddress:="'ws.name'", _
TextToDisplay:="'ws.name'"
i = i + 1
Next ws
End Sub
Altered your code a bit - this now works:
Sub GetHyperlinks()
Dim ws As Worksheet
Dim i As Integer
i = 4
For Each ws In ThisWorkbook.Worksheets
ActiveWorkbook.Sheets("overview").Hyperlinks.Add _
Anchor:=ActiveWorkbook.Sheets("overview").Cells(i, 1), _
Address:="", _
SubAddress:="'" & ws.Name & "'!A1", _
TextToDisplay:=ws.Name
i = i + 1
Next ws
End Sub
Two methods are used to create the links to the Active Workbook Sheets:
Simple hyperlinks are created for standard Worksheets.
Less commonly used Chart Sheets — and even rarer Dialog Sheets — cannot be hyperlinked. If this code detects a non-Worksheet type, a Sheet BeforeDoubleClick event is programmatically added to the TOC sheet so that these Sheets can still be referenced via a short cut.
Note that (2) requires that macros are enabled for this approach to work.
Option Explicit
Sub CreateTOC()
Dim ws As Worksheet
Dim nmToc As Name
Dim rng1 As Range
Dim lngProceed As Boolean
Dim bNonWkSht As Boolean
Dim lngSht As Long
Dim lngShtNum As Long
Dim strWScode As String
Dim vbCodeMod
'Test for an ActiveWorkbook to summarise
If ActiveWorkbook Is Nothing Then
MsgBox "You must have a workbook open first!", vbInformation, "No Open Book"
Exit Sub
End If
'Turn off updates, alerts and events
With Application
.ScreenUpdating = False
.DisplayAlerts = False
.EnableEvents = False
End With
'If the Table of Contents exists (using a marker range name "TOC_Index") prompt the user whether to proceed
On Error Resume Next
Set nmToc = ActiveWorkbook.Names("TOC_Index")
If Not nmToc Is Nothing Then
lngProceed = MsgBox("Index exists!" & vbCrLf & "Do you want to overwrite it?", vbYesNo + vbCritical, "Warning")
If lngProceed = vbYes Then
Exit Sub
Else
ActiveWorkbook.Sheets(Range("TOC_Index").Parent.Name).Delete
End If
End If
Set ws = ActiveWorkbook.Sheets.Add
ws.Move before:=Sheets(1)
'Add the marker range name
ActiveWorkbook.Names.Add "TOC_INDEX", ws.[a1]
ws.Name = "TOC_Index"
On Error GoTo 0
On Error GoTo ErrHandler
For lngSht = 2 To ActiveWorkbook.Sheets.Count
'set to start at A6 of TOC sheet
'Test sheets to determine whether they are normal worksheets
ws.Cells(lngSht + 4, 2).Value = TypeName(ActiveWorkbook.Sheets(lngSht))
If TypeName(ActiveWorkbook.Sheets(lngSht)) = "Worksheet" Then
'Add hyperlinks to normal worksheets
ws.Hyperlinks.Add Anchor:=ws.Cells(lngSht + 4, 1), Address:="", SubAddress:="'" & ActiveWorkbook.Sheets(lngSht).Name & "'!A1", TextToDisplay:=ActiveWorkbook.Sheets(lngSht).Name
Else
'Add name of any non-worksheets
ws.Cells(lngSht + 4, 1).Value = ActiveWorkbook.Sheets(lngSht).Name
'Colour these sheets yellow
ws.Cells(lngSht + 4, 1).Interior.Color = vbYellow
ws.Cells(lngSht + 4, 2).Font.Italic = True
bNonWkSht = True
End If
Next lngSht
'Add headers and formatting
With ws
With .[a1:a4]
.Value = Application.Transpose(Array(ActiveWorkbook.Name, "", Format(Now(), "dd-mmm-yy hh:mm"), ActiveWorkbook.Sheets.Count - 1 & " sheets"))
.Font.Size = 14
.Cells(1).Font.Bold = True
End With
With .[a6].Resize(lngSht - 1, 1)
.Font.Bold = True
.Font.ColorIndex = 41
.Resize(1, 2).EntireColumn.HorizontalAlignment = xlLeft
.Columns("A:B").EntireColumn.AutoFit
End With
End With
'Add warnings and macro code if there are non WorkSheet types present
If bNonWkSht Then
With ws.[A5]
.Value = "This workbook contains at least one Chart or Dialog Sheet. These sheets will only be activated if macros are enabled (NB: Please doubleclick yellow sheet names to select them)"
.Font.ColorIndex = 3
.Font.Italic = True
End With
strWScode = "Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)" & vbCrLf _
& " Dim rng1 As Range" & vbCrLf _
& " Set rng1 = Intersect(Target, Range([a6], Cells(Rows.Count, 1).End(xlUp)))" & vbCrLf _
& " If rng1 Is Nothing Then Exit Sub" & vbCrLf _
& " On Error Resume Next" & vbCrLf _
& " If Target.Cells(1).Offset(0, 1) <> ""Worksheet"" Then Sheets(Target.Value).Activate" & vbCrLf _
& " If Err.Number <> 0 Then MsgBox ""Could not select sheet"" & Target.Value" & vbCrLf _
& "End Sub" & vbCrLf
Set vbCodeMod = ActiveWorkbook.VBProject.VBComponents(ws.CodeName)
vbCodeMod.CodeModule.AddFromString strWScode
End If
'tidy up Application settins
With Application
.ScreenUpdating = True
.DisplayAlerts = True
.EnableEvents = True
End With
ErrHandler:
If Err.Number <> 0 Then MsgBox Err.Description & vbCrLf & "Please note that your Application settings have been reset", vbCritical, "Code Error!"
End Sub
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
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