Excel VBA adding data to a chart - vba

Hello I have a little question for adding data to an existing chart.
Now I have a worksheet containing a data series with months for the years in the 2nd row of the sheet. So the months are for example B2 1.2017, C2 2.2017, and in the rows 3,4,5,6,7 and 8 there is always data for that month.
Now I just want my macro to add the new Month plus the data of the rows below to my existing chart.
the code I have so far is this:
Worksheets("Summary").ChartObjects("Chart").Activate
ActiveChart.SeriesCollection.Add _
Source:=Worksheets("Summary").Range("B2:B8")
now this does just create new data series but there is actually no new data added to the chart.

The code below might seem a little long, but it's the safest way to add a new Series with Data to an existing Chart.
I'm setting all the necessary Objects so the code will be as "safe-proof" as can be.
Code
Option Explicit
Sub AddSeriestoChart()
Dim ws As Worksheet
Dim ChtRng As Range
Dim ChtObj As ChartObject
Dim Ser As Series
' set the Worksheet object
Set ws = ThisWorkbook.Worksheets("Summary")
' Set the Chart Object
Set ChtObj = ws.ChartObjects("Chart")
' Set the Range of the Chart's source data
Set ChtRng = ws.Range("B2:B8")
With ChtObj
' add a new series to chart
Set Ser = .Chart.SeriesCollection.NewSeries
' set the source data of the new series
Ser.Values = "=" & ChtRng.Address(False, False, xlA1, xlExternal)
End With
End Sub
Edit 1: to modify existing Series data, use something like the code below :
With ChtObj
For i = 1 To .Chart.SeriesCollection.Count
Set Ser = .Chart.SeriesCollection(i)
' set the source data of the new series
Set ChtRng = ws.Range("B" & i + 2)
Ser.Values = "=" & ChtRng.Address(False, False, xlA1, xlExternal)
Set ChtRng = Nothing
Next i
End With

This is what I would use
wsMetric.ChartObjects("Chart").Chart
'This one will link data from another workbook
.SeriesCollection(1).Values = "='[" & wb.Name & "]" & ws.Name & "'!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow2
'Debug.Print "='[" & wb.Name & "]" & ws.Name & "'!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow2 'Returns ='[Book1.xlsm]Sheet1'!$A$1:$A$11
'This one will link data from the same workbook, same or different sheet
.SeriesCollection(1).Values = "=" & ws.Name & "!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow 2
'Debug.print "=" & ActiveSheet.Name & "!$" & scol & "$" & lrow & ":$" & scol2 & "$" & lrow2 'Returns =Sheet1!$A$1:$A$11
End With
This doesn't use .Activate and directly accesses the chart

Related

Rearranging columns and exIporting range to CSV

I have a set of data that is downloaded from SQL Server. Data can be huge. I need to rearrange it to a specific column order template before exporting it to either CSV or XLSX, really does not matter.
In this instance, I have put together a code that takes the original data (From Col A to Co; Q and set them up in the same sheet from Col T to Col AB) then attempt to export that range (T:AB to Last row) as CSV.
First part of the code works, pretty straightforward. However, I am struggling to export the range to either CSV or XLSX. Currently it is exporting data into another file only in row 1.
CODE
Sub test()
Dim LR As Long
Dim myCSVFileName As String
Dim myWB As Workbook
Dim rngToSave As range
Dim fNum As Integer
Dim csvVal As String
LR = Sheets("AAP").Cells(Rows.count, "A").End(xlUp).row
Sheets("AAP").range("T2:T" & LR).Value = Sheets("AAP").range("B2:B" & LR).Value
Sheets("AAP").range("U2:U" & LR).Value = Sheets("AAP").range("C2:C" & LR).Value
Sheets("AAP").range("V2:V" & LR).Value = Sheets("AAP").range("I2:I" & LR).Value
Sheets("AAP").range("W2:W" & LR).Value = Sheets("AAP").range("J2:J" & LR).Value
Sheets("AAP").range("X2:X" & LR).Value = Sheets("AAP").range("E2:E" & LR).Value
Sheets("AAP").range("Y2:Y" & LR).Value = Sheets("AAP").range("F2:F" & LR).Value
Sheets("AAP").range("Z2:Z" & LR).Value = Sheets("AAP").range("H2:H" & LR).Value
Sheets("AAP").range("AA2:AA" & LR).Value = Sheets("AAP").range("G2:G" & LR).Value
Sheets("AAP").range("AB2:AB" & LR).Value = "AA_FEES"
Set myWB = ThisWorkbook
myCSVFileName = myWB.Path & "\" & "CSV-Exported-File-" & VBA.Format(VBA.Now, "dd-MMM-yyyy hh-mm") & ".csv"
csvVal = ""
fNum = FreeFile
Set rngToSave = range("T2:AB" & LR)
Open myCSVFileName For Output As #fNum
For i = 1 To rngToSave.Rows.count
For j = 1 To rngToSave.Columns.count
csvVal = csvVal & Chr(34) & rngToSave(i, j).Value & Chr(34) & ","
Next
Print #fNum, Left(csvVal, Len(csvVal) - 2)
csvVal = ""
Next
Close #fileNumber
End Sub
Any advise how to make this more efficient would be greatly appreciated.
The easiest method to export that to a CSV would be to copy the worksheet to no destination. This creates a new workbook that is the new ActiveWorkbook with a single worksheet that is a copy of the original. After deleting columns A:S, SaveAs xlCSV.
...
workSheets("AAP").copy
with activeworkbook
application.displayalerts = false
.worksheets(1).range("A:S").entirecolumn.delete
.saveas filename:=myCSVFileName, fileformat:=xlcsv
.close savechanges:=false
application.displayalerts = true
end with

Simple VBA Throwing Object Error 1004

This loops through each worksheet and inserts a VLOOKUP formula (which references a closed workbook). The code will start with the first sheet, find and open the corresponding workbook, and perform the VLOOKUP, then onto the next sheet/corresponding workbook. Everything works until I hit .Cells which is where i run into the Object error. What am I missing? I run this macro from the original workbook, then it opens the external workbook
For Each ws In ThisWorkbook.Worksheets
If (ws.Name <> "Sheet1") And (ws.Name <> "Sheet2") Then
Set wbPath2 = Workbooks.Open("C:\MyDirectory\MyFile1.csv")
sourceSheet = "[MySheet.csv]"
With ws
.Cells(Application.WorksheetFunction.Match("Account1", .Range("A:A"), 0), Application.WorksheetFunction.Match(ComboBox1.Value & " " & Year(Date), .Range("A6:BZ6"), 0)).Formula = "=VLOOKUP(""Account1 Service"",'" & Root & sourceSheet & ws.Name & " " & monthNumber & "." & lastDay & "." & Format(Now(), "yy") & "'!$A:$G,4,FALSE)"
It turns out I forgot to concatenate something in my file path pointer. Thank you to #Jordan for the Debug tips.
the object seems to ComboBox1.Value .
In sheet code, it is possible to use combobox. But in module, it is not possible. So use obleObject and link cell. And get the cell value.
Dim ws As Worksheet
Dim obj As OLEObject
Dim strCombo As String
For Each ws In ThisWorkbook.Worksheets
If (ws.Name = "Sheet1") Or (ws.Name = "Sheet2") Then
Else
Set wbPath2 = Workbooks.Open("C:\MyDirectory\MyFile1.csv")
sourceSheet = "[MySheet.csv]"
With ws
k = .Name
Set obj = .OLEObjects("ComboBox1")
obj.LinkedCell = "q1" 'your blank cell link ; this link "q1" cell
strCombo = .Range("q1")
.Cells(Application.WorksheetFunction.Match("Account1", .Range("A:A"), 0), Application.WorksheetFunction.Match(strCombo & " " & Year(Date), .Range("A6:BZ6"), 0)).Formula = "=VLOOKUP(""Account1 Service"",'" & Root & sourceSheet & ws.Name & " " & monthNumber & "." & lastDay & "." & Format(Now(), "yy") & "'!$A:$G,4,FALSE)"
.Range("q1").Clear
End With
End If
Next

Loop and set value for coulmns

I am currently using the set value method to copy data from multiple workbooks. I can currently loop through all workbooks and set the values from one sheet, worksheet2(Title) as seen below, and copy them to "thisWorkbook" on "sheet1", my destination. How can I loop through worksheets 3 to 9 and copy the range A2:C57 into columns G,H,I using the same set value method?
Sub GetData()
Dim MyPath As String
Dim FileName As String
Dim SheetName As String
Dim NewRow As Long
MyPath = "C:\attach"
SheetName = "Title"
FileName = Dir(MyPath & "\*.xlsx")
Do While FileName <> ""
If FileName <> ThisWorkbook.Name Then
With ThisWorkbook.Sheets("Sheet1")
NewRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
With .Range("A" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B4"
.Value = .Value
End With
With .Range("B" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B5"
.Value = .Value
End With
With .Range("C" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B6"
.Value = .Value
End With
With .Range("D" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B7"
.Value = .Value
End With
With .Range("E" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!A1"
.Value = .Value
End With
With .Range("F" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!A2"
.Value = .Value
End With
'Copy the range A2:C57 from workheets (3 to 9) and past into columns G,H,I in thisworkbook from every workbook in folder.
'For sheets 3 to 9 set the value range A2:C57 to G,H,I in thisworkbook. This would be done for every workbook in the folder
End With
End If
FileName = Dir
Loop
ThisWorkbook.Sheets("Sheet1").Columns.AutoFit
End Sub
I'm not entirely sure if this is what you're asking, but I think the range.copy is what you want.
To get the entire worksheet 3-9 you can use
' A2:C57 = Cells (2,1),Cells(57,3)
For Sheetindex= 3 to ThisWorkbook.Worksheets.Count
'Copy Worksheet 3 A2:C57
Set SourceRange = ThisWorkbook.WorkSheets(Sheetindex).Range(Cells(2,1),Cells(57,3))
' Paste it in Columns G,H,I starting in Row 1.
SourceRange.Copy (ThisWorkbook.Worksheets("Sheet1").Cells("G1"))
Next Sheetindex

Application defined or object defined error - depending on which Worksheet is opened

I'm having an issue that I am struggling to solve as it's a bit specific. I have code that does copy and paste from one sheet to others. Each part of the code basically copies part from the master sheet "current" to the specified sheet.
When I run my code I receive an error "Application defined or object defined error" and the code stops at the work sheet "Dividend yield" after the following line
Worksheets("div. yield").Range("B7").Select
However if I open the sheet "Dividend yield" and run my code from there it will work fine until the last sheet "Reverse PE" where it will again throw and error "Application defined or object defined error" after the line
Worksheets("Reverse_PE").Range("B9").Select
I guess the error is related to the next coming rows with Autofill method but I have not found any useful solutions to this problem. Could somebody please advise me how to solve this error?
Full macros code is below.
Function getYield() As Double
Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")
With appIE
.Navigate "http://uk.investing.com/rates-bonds/world-government-bonds"
.Visible = False
End With
Do While appIE.Busy
DoEvents
Loop
Set allRowOfData = appIE.document.getElementById("pair_23705")
Dim myValue As Double: myValue = allRowOfData.Cells(2).innerHTML
appIE.Quit
Set appIE = Nothing
Worksheets("Reverse_PE").Range("B7").Value = myValue
Worksheets("Reverse_PE").Range("B7").Value = Worksheets("Reverse_PE").Range("B7").Value / 100
End Function
Sub adjust()
Dim copyAdress As Range
Dim copyRange As Range
Dim lastRow As Long
Dim Median As Range
'''PE'''
Set copyAdress = Worksheets("current").Range("A1:CJ10000").Find("PE_RATIO", lookat:=xlPart)
lastRow = Cells(65536, copyAdress.Column).End(xlUp).Row
Set copyRange = Worksheets("current").Range(Cells(copyAdress.Row + 1, copyAdress.Column), Cells(lastRow, copyAdress.Column))
Worksheets("PE").Range("B1").EntireColumn.Insert
copyRange.Copy Destination:=Sheets("PE").Range("B7", "B" & lastRow)
Worksheets("PE").Range("B2").Value = Worksheets("current").Range("A1").Value
Worksheets("PE").Range("B3").FormulaArray = "=MEDIAN(B7:B" & lastRow + 2 & ")"
Worksheets("PE").Range("B5").Font.Bold = True
Worksheets("PE").Range("B5").FormulaArray = "=IF(ISNUMBER(VLOOKUP($A$5,$A$7:$HI$1750,COLUMN(B4),FALSE)),VLOOKUP($A$5,$A$7:$HI$1750,COLUMN(B4),FALSE)," & Chr(34) & NA & Chr(34) & ")"
Set copyRange = Worksheets("current").Range("A5", "A" & lastRow)
copyRange.Copy Destination:=Sheets("PE").Range("A7", "A" & lastRow + 2)
''Dividend yield'''
Set copyRange = Worksheets("current").Range("A5", "A" & lastRow)
copyRange.Copy Destination:=Sheets("div. yield").Range("A7", "A" & lastRow + 2)
Worksheets("div. yield").Range("B7").FormulaArray = "=IF(ISNUMBER(current!X5),current!X5," & Chr(34) & Chr(34) & ")"
Worksheets("div. yield").Range("B7").Select
Selection.AutoFill Destination:=Sheets("div. yield").Range("B7:B" & lastRow + 2), Type:=xlFillDefault
'''PE Forward'''
Set copyAdress = Worksheets("current").Range("A1:CJ10000").Find("P/E-Ratio 03E", lookat:=xlPart)
lastRow = Cells(65536, copyAdress.Column).End(xlUp).Row
Set copyRange = Worksheets("current").Range(Cells(copyAdress.Row + 3, copyAdress.Column), Cells(lastRow, copyAdress.Column))
Worksheets("PE_forward").Range("B1").EntireColumn.Insert
copyRange.Copy Destination:=Sheets("PE_forward").Range("B7", "B" & lastRow + 2)
Worksheets("PE_forward").Range("B2").Value = Worksheets("current").Range("A1").Value
Worksheets("PE_forward").Range("B3").FormulaArray = "=MEDIAN(B7:B" & lastRow + 2 & ")"
Worksheets("PE_forward").Range("B5").Font.Bold = True
Worksheets("PE_forward").Range("B5").FormulaArray = "=IF(ISNUMBER(VLOOKUP($A$5,$A$7:$HI$1750,COLUMN(B751),FALSE)),VLOOKUP($A$5,$A$7:$HI$1750,COLUMN(B751),FALSE)," & Chr(34) & NA & Chr(34) & ")"
Worksheets("PE_forward").Columns("B").Replace What:="#VALUE!", Replacement:=""
Worksheets("PE_forward").Range("B3").NumberFormat = ""
Set copyRange = Worksheets("current").Range("A5", "A" & lastRow)
copyRange.Copy Destination:=Sheets("PE_forward").Range("A7", "A" & lastRow + 2)
'''Reverse PE'''
Set copyRange = Worksheets("current").Range("A5", "A" & lastRow)
copyRange.Copy Destination:=Sheets("Reverse_PE").Range("A9", "A" & lastRow + 4)
Worksheets("Reverse_PE").Range("B1").EntireColumn.Insert
Worksheets("Reverse_PE").Range("B2").Value = Worksheets("current").Range("A1").Value
Worksheets("Reverse_PE").Range("B5").FormulaArray = "=IF(ISNUMBER(VLOOKUP($A$5,$A$9:$HI$1750,COLUMN(B751),FALSE)),VLOOKUP($A$5,$A$9:$HI$1750,COLUMN(B751),FALSE)," & Chr(34) & NA & Chr(34) & ")"
getYield
Worksheets("Reverse_PE").Range("B3").FormulaArray = "=MEDIAN(B9:B" & lastRow + 4 & ")"
Worksheets("Reverse_PE").Range("B9").FormulaArray = "=IF(ISNUMBER(PE!B7),1/PE!B7," & Chr(34) & Chr(34) & ")"
Worksheets("Reverse_PE").Range("B9").Select
Selection.AutoFill Destination:=Sheets("Reverse_PE").Range("B9:B" & lastRow + 4), Type:=xlFillDefault
Worksheets("Reverse_PE").Range("B3:B" & lastRow + 4).Select
Selection.Style = "Percent"
Selection.NumberFormat = "0.00%"
You can't use the select method unless the sheet is first active, so add this line:
Worksheets("div. yield").Activate
Worksheets("div. yield").Range("B7").FormulaArray = "=IF(ISNUMBER(current!X5),current!X5," & Chr(34) & Chr(34) & ")"
and later at:
Worksheets("Reverse_PE").Activate
Worksheets("Reverse_PE").Range("B9").Select
There are much faster and more maintainable ways of doing what you're trying to do, but the above sheet activation will solve your immediate problem.
Don't forget to activate each sheet before you try to select one of the cells on it.

Using String Variable in VBA Formula throwing object/application error

I'm getting an "application-defined or object-defined error" being thrown when I try to set a cell in my active sheet to a formula. I think its due to me trying to use the Sheets.Name function in the formula, see code below:
Public Sub getChannels()
Dim lastRow As Long
Dim i As Integer, counter As Integer
Dim rng As Range, rngB As Range, rngC As Range
Dim sht As Worksheet
Dim test As String
Set sht = Sheets("Summary Sheet - 30-07-2015")
sht.Activate
lastRow = sht.Cells(sht.Rows.Count, "B").End(xlUp).Row
For counter = 1 To lastRow Step 3
If ActiveSheet.Cells(counter, 12) = "LTE 2C" Then
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH(""'"" & sht.name &""'""!RC[-14],'LTE 2C'!C[-11],0))"
ActiveSheet.Cells(counter, 17) = _
"=INDEX('LTE 2C'!C[53],MATCH(""'"" & sht.name &""'""!RC[-15],'LTE 2C'!C[-12],0))"
ActiveSheet.Cells(counter, 18) = _
"=INDEX('LTE 2C'!C[55],MATCH(""'"" & sht.name &""'""!RC[-16],'LTE 2C'!C[-13],0))"
Range("P" & counter & ":R" & counter).Select
Selection.Copy
Range("P" & counter + 1 & ":P" & counter + 2).Select
ActiveSheet.Paste
End If
Next
End Sub
Am I missing something obvious?
Change your formula like this:
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH(" & "'" & sht.name & "'" & "!RC[-14],'LTE 2C'!C[-11],0))"
ActiveSheet.Cells(counter, 17) = _
"=INDEX('LTE 2C'!C[53],MATCH(" & "'" & sht.name & "'" & "!RC[-15],'LTE 2C'!C[-12],0))"
ActiveSheet.Cells(counter, 18) = _
"=INDEX('LTE 2C'!C[55],MATCH(" & "'" & sht.name & "'" & "!RC[-16],'LTE 2C'!C[-13],0))"
Nelly is correct, but another way to do this would be to simply remove the unnecessary extra string for each apostrophe and replace it with this:
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH('" & sht.name & "'!RC[-14],'LTE 2C'!C[-11],0))"
Where the apostrophes are just attached to the strings before and after. It really makes no difference, but it removes the extra (&)s.