Here is the code:
numLoansSoldPrev = Range("LoansSold:NewHedges").Cells.Count
If numLoansSoldPrev > 3 Then
Set rngLoansSoldStart = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(1, 1)
Let strLoansSoldStart = rngLoansSoldStart.Address
Set rngLoansSoldEnd = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(-2, 5)
Let strLoansSoldEnd = rngLoansSoldEnd.Address
Range(strLoansSoldStart & ":" & strLoansSoldEnd).Select
Selection.ClearContents
End If
The commands below the beginning of the if statement work just fine on their own, but every time I try to execute this, I get "block if without end if" despite clearly having one at the bottom.
I have numerous of these if statements in the file but they are all in the same format, so it's not like one if statement is missing an end if.
Any idea?
Expanded Code:
' DECLARE NEW LONGS VARIABLES
Dim numNewLoansPrev As Integer
Dim rngLoansStart As Range
Dim rngLoansEnd As Range
Dim strLoansStart As String
Dim strLoansEnd As String
' DECLARE NEW LOANS SOLD VARIABLES
Dim numLoansSoldPrev As Integer
Dim rngLoansSoldStart As Range
Dim rngLoansSoldEnd As Range
Dim strLoansSoldStart As String
Dim strLoansSoldEnd As String
' DECLARE NEW HEDGES VARIABLES
Dim numNewHedges As Integer
Dim rngNewHedgesStart As Range
Dim rngNewHedgesEnd As Range
Dim strNewHedgesStart As String
Dim strNewHedgesEnd As String
Dim xcess As Integer
' Active E-mail Tab
Worksheets("Email").Activate
' CLEAR EXCESS NEW LONG POSITIONS
numNewLoansPrev = Range("NewLongs:LoansSold").Cells.Count
If numNewLoansPrev > 3 Then
Set rngLoansStart = ActiveWorkbook.Sheets("Email").Range("NewLongs").Offset(1, 1)
Set strLoansStart = rngLoansStart.Address
Set rngLoansEnd = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(-2, 5)
Set strLoansEnd = rngLoansEnd.Address
Range(strLoansStart & ":" & strLoansEnd).Select
Selection.ClearContents
End If
' CLEAR EXCESS SOLD LONG POSITIONS
numLoansSoldPrev = Range("LoansSold:NewHedges").Cells.Count
If numLoansSoldPrev > 3 Then
Set rngLoansSoldStart = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(1, 1)
Set strLoansSoldStart = rngLoansSoldStart.Address
Set rngLoansSoldEnd = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(-2, 5)
Set strLoansSoldEnd = rngLoansSoldEnd.Address
Range(strLoansSoldStart & ":" & strLoansSoldEnd).Select
Selection.ClearContents
End If
' CLEAR EXCESS NEW HEDGES POSITIONS
numNewHedges = Range("NewHedges:Pnl").Cells.Count
If numNewHedges > 3 Then
Set rngNewHedgesStart = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(1, 1)
Set strNewHedgesStart = rngNewHedgesStart.Address
Set rngNewHedgesEnd = ActiveWorkbook.Sheets("Email").Range("PnL").Offset(-2, 5)
Set strNewHedgesEnd = rngNewHedgesEnd.Address
Range(strNewHedgesStart & ":" & strNewHedgesEnd).Select
Selection.ClearContents
End If
Related
I have a Word doc with some numbers referred in the foot notes. and I am exporting these references as a csv file.
Sub FindNumber()
Dim exp, exp1 As RegExp
Set exp = New RegExp
exp.Pattern = "\b[A-Za-z]{3}[0-9]{7}\b"
exp.Global = True
Dim splits(1000) As String
Dim x As Long
Dim results As MatchCollection
Set results = exp.Execute(ActiveDocument.StoryRanges(wdFootnotesStory))
x = 1
For Each res In results
splits(x) = res
x = x + 1
Next res
Dim Filename As String, line As String
Dim i As Integer
Filename = "C:\VBA Export" & "\Numbers.csv"
Open Filename For Output As #2
Print #2, "Control Numbers"
For i = LBound(splits) To UBound(splits)
Print #2, splits(i)
Next i
Close #2
MsgBox "Numbers were exported to " & Filename, vbInformation
End Sub
The code above was working fine and just suddenly starting throwing error at 'splits(x) = res'
I have tried checking my regex and I can see that it works fine. If I change splits(x) to splits(6) or something similar it works like a charm .
Can someone please help ?
EDIT - changed code to write matches directly to Excel.
Sub Tester()
Dim oXl As Excel.Application 'add reference to MS Excel object library...
Dim oWb As Excel.Workbook, c As Excel.Range, i As Long, col As Collection
Set oXl = New Excel.Application
oXl.Visible = True
Set oWb = oXl.Workbooks.Add()
Set c = oWb.Worksheets(1).Range("A1")
ListMatchesInExcel ActiveDocument.StoryRanges(wdFootnotesStory), _
"\b[A-Za-z]{3}[0-9]{7}\b", _
"Id Numbers", c
Set c = c.Offset(0, 1)
ListMatchesInExcel ActiveDocument.StoryRanges(wdFootnotesStory), _
"\b[A-Za-z]{2}[0-9]{9}\b", _
"Other Numbers", c
Set c = c.Offset(0, 1)
'etc etc
End Sub
'Search through `SearchText` for text matching `patt` and export all
' matches to Excel with a header `HeaderText`, starting at range `c`
Sub ListMatchesInExcel(SearchText As String, patt As String, _
headerText As String, c As Excel.Range)
'add reference to MicroSoft VBscript regular expressions
Dim exp, exp1 As RegExp, col As New Collection
Dim results As MatchCollection, res As Match, i As Long
Set exp = New RegExp
exp.Pattern = patt
exp.Global = True
Set results = exp.Execute(SearchText)
'log to Immediate pane
Debug.Print (col.Count - 1) & " matche(s) for '" & patt & "'"
c.Value = headerText
i = 1
For Each res In results
c.Offset(i).Value = res
i = i + 1
Next res
c.EntireColumn.AutoFit
End Sub
I need to be able to identify the worksheet that an excel chart (on a worksheet) is getting it's data from. I only need the data sheet which series 1 is referencing. I've started trying to extract the sheet name from .SeriesCollection(1).Formula but it gets realy complex. here's what I've got so far:
Sub GetChartDataSheet()
Dim DataSheetName As String
Dim DataSheet As Worksheet
DataSheetName = ActiveChart.SeriesCollection(1).Formula
DataSheetName = Left(DataSheetName, InStr(1, DataSheetName, "!$") - 1)
DataSheetName = WorksheetFunction.Replace(DataSheetName, 1, Len("=series("), "")
If Left(DataSheetName, 1) = "'" And Right(DataSheetName, 1) = "'" Then DataSheetName = Mid(DataSheetName, 2, Len(DataSheetName) - 2)
DataSheetName = Replace(DataSheetName, "''", "'")
Set DataSheet = Sheets(DataSheetName)
End Sub
this works in a lot of cases, but if my users have a strange worksheet name (eg Sh'e e$,,t!3!$) it fails. the same goes if series 1 has been named (eg .SeriesCollection(1).Formula = "=SERIES(**"Hell,o !"**,'Sh''e e$,,t!3!$'!$B$2:$B$18,'Sh''e e$,,t!3!$'!$C$2:$C$18,1)".
Is there a simple way to solve this?
I thought this is an easy one, turns out it's not. One of the cases where Excel has the information but will not give it away for free. I ended up with a function like this - maybe this helps:
Function getSheetNameOfSeries(s As Series) As String
Dim f As String, i As Integer
Dim withQuotes As Boolean
' Skip leading comma if not all parts of series is filled. Check if sheetname is in single quotes
For i = 9 To Len(s.Formula)
If Mid(s.Formula, i, 1) <> "," Then
If Mid(s.Formula, i, 1) = "'" Then
withQuotes = True
f = Mid(s.Formula, i + 1)
Else
withQuotes = False
f = Mid(s.Formula, i)
End If
Exit For
End If
Next i
' "f" now contains a part of the formula with the sheetname as start
' now we search to the end of the sheet name.
' If name is in quotes, we are looking for the "closing" quote
' If not in quotes, we are looking for "!"
i = 1
Do While True
If withQuotes Then
' Sheet name is in quotes, found closes quote --> we're done
' (but if next char is also a quote, we have the case the the sheet names contains a quote, so we have to continue working)
If Mid(f, i, 1) = "'" Then
If Mid(f, i + 1, 1) <> "'" Then
getSheetNameOfSeries = Mid(f, 1, i - 1)
Exit Do
Else
i = i + 1 ' Skip 2nd quote
End If
End If
Else
' Sheet name is quite normal, so "!" will indicate the end of sheetname
If Mid(f, i, 1) = "!" Then
getSheetNameOfSeries = Mid(f, 1, i - 1)
Exit Do
End If
End If
i = i + 1
Loop
getSheetNameOfSeries = Replace(getSheetNameOfSeries, "''", "'")
End Function
You can use the Find function to look for the values of SeriesCollection(1).
In the worksheet that hold the data of SeriesCollection(1), you will be able to find all the values in that array.
More explanations inside the code below.
Code
Option Explicit
Sub GetChartDataSheet()
Dim DataSheetName As String
Dim DataSheet As Worksheet
Dim ws As Worksheet
Dim ValuesArr As Variant, Val As Variant
Dim FindRng As Range
Dim ShtMatch As Boolean
Dim ChtObj As ChartObject
Dim Ser As Series
' if you want to use ActiveChart
Set ChtObj = ActiveChart.Parent
Set Ser = ChtObj.Chart.SeriesCollection(1)
ValuesArr = Ser.Values ' get the values of the Series Collection inside an array
' use Find to get the Sheet's origin
For Each ws In ThisWorkbook.Sheets
With ws
ShtMatch = True
For Each Val In ValuesArr ' loop through all values in array
Set FindRng = .Cells.Find(what:=Val) ' you need to find each value in the worksheet that SeriesCollection data is tied to
If FindRng Is Nothing Then
ShtMatch = False
Exit For
End If
Set FindRng = Nothing ' reset
Next Val
If ShtMatch = True Then
Set DataSheet = ws
Exit For
End If
End With
Next ws
DataSheetName = DataSheet.Name
End Sub
I am trying to create a VB macro in Visio that can read the data and properties of the shape. So say I have a Rectangle Shpae in Visio with Cells Name, Description, Type, Size.... and so on.
When I try to read the cells and their values I am only getting the first cell and its value.
Here is my code . I would appreciate some help here.
Sub Testing()
Dim excelObj As Object
Dim excelFile As String
Dim sheetName As String
' Dim excelBook As Excel.Workbook
' Set excelFile = "C:\Users\hbhasin\Documents\test.xls"
'Set sheetName = "New Sheet name"
Set excelObj = CreateObject("Excel.Application")
excelObj.Workbooks.Add
Dim pagObj As Visio.Page
Dim shpsObj As Visio.shapes
Dim shapes As Visio.shapes
Dim shpObj As Visio.Shape
Dim CellObj As Visio.Cell
Dim Storage() As String
Dim iShapeCount As Integer
Dim i As Integer
Dim j As Integer
Set pagObj = ActivePage
Set shpsObj = pagObj.shapes
iShapeCount = shpsObj.Count
Debug.Print iShapeCount
ReDim Storage(8, iShapeCount - 1)
For i = 1 To iShapeCount - 1
Set shpObj = shpsObj(i)
Storage(1, i - 1) = shpObj.Name
If shpObj.CellExists("Prop.Name", visExistsLocally) Then
Set CellObj = shpObj.CellsU("Prop.Name")
Storage(2, i - 1) = CellObj.ResultStr("")
End If
If shpObj.CellExists("Prop.Description", visExistsLocally) Then
Debug.Print "Test the IF statement"
Set CellObj = shpObj.CellsU("Prop.Description")
Storage(3, i - 1) = CellObj.ResultStr("")
End If
Next
For i = 0 To iShapeCount - 1
Debug.Print "Name- " & Storage(0, i)
Debug.Print "Description-" & Storage(1, i)
Next
End Sub
In fact, I have put a debug statement within the second if clause and that does not execute which tells me the compiler is not even seeing the second cell or any cell after.
If you're not getting the Description Shape Data it maybe that it's not local, but inherited from its master. Here's a slight modification of your code (with the Excel part removed as I don't think it's relevant here):
Sub Testing()
Dim shpsObj As Visio.shapes
Set shpsObj = ActivePage.shapes
Dim iShapeCount As Integer
iShapeCount = shpsObj.Count
'Assumes you want an array of shape data
Dim Storage() As String
ReDim Storage(iShapeCount - 1, 2)
'Visio shapes are 1 based so use full count
Dim i As Integer
Dim shpObj As Visio.Shape
For i = 1 To iShapeCount
Set shpObj = shpsObj(i)
Storage(i - 1, 0) = shpObj.Name 'Do you want NameU?
'Assumes you don't care whether the cell is local or inherited
If shpObj.CellExistsU("Prop.Name", visExistsAnywhere) Then
Storage(i - 1, 1) = shpObj.CellsU("Prop.Name").ResultStr("")
End If
If shpObj.CellExistsU("Prop.Description", visExistsAnywhere) Then
Storage(i - 1, 2) = shpObj.CellsU("Prop.Description").ResultStr("")
End If
Next
Dim j As Long
For j = LBound(Storage, 1) To UBound(Storage, 1)
Debug.Print "Shape Name- " & Storage(j, 0)
Debug.Print " Prop.Name- " & Storage(j, 1)
Debug.Print " Prop.Description- " & Storage(j, 2)
Next j
End Sub
If you're just running through all the shapes on the page, then you might want to look at For Each shp In shapes as an alternative. Check out this page for more details:
http://visualsignals.typepad.co.uk/vislog/2007/11/looping-through.html
Also, you might want to try look at the CreateSelection page method to narrow down your target shapes if you're dealing with a large number
I have an Excel file for colleagues to extract reports from SQL server.
We created separate user and password for their department.
I have the module which shows the result of SQL query in an Excel file.
Here is working code:
Sub Button3_Click()
ActiveSheet.Cells.Clear
Dim qt As QueryTable
sqlstring1 = "SELECT * FROM dbo.ReportDataAdded ORDER BY ProductID, CountryCodeID"
With ActiveSheet.QueryTables.Add(Connection:=getConnectionStr2, Destination:=Range("A3"), Sql:=sqlstring1)
.Refresh
End With
End Sub
Private Function getConnectionStr2()
getConnectionStr2 = "ODBC;DRIVER={SQL Server};" & _
"DATABASE=em_CountryConsumer;" & _
"SERVER=192.192.192.192;" & _
"UID=UserName;" & _
"PWD=passwordd;"
End Function
I need to populate the result of another query into combo box. For that I need to get result of query into variable with dataset datatype.
How can I change my VBA code to do that?
Here is an example of how I have handled a similar problem in the past:
First here is a function to Query the database based with a given connection_string and query.
Function GetQuery(SQL As String, connect_string As String, Optional HasFields As Long = 0) As Variant
'''
' Returns: A Variant() Array with results from query.
'
' HasFields is an optional field to include the field names in the array
' Any integer in this field will include fields, leave it blank for just data
'''
Dim Conn As New ADODB.Connection
Dim RS As New ADODB.Recordset
Dim data_sheet As Worksheet
Dim R As Long, C As Long
Dim dbArr() As Variant
'''''''''''''''''''''''''''''
' Setting Up DB connection
'''''''''''''''''''''''''''''
conReTry:
On Error GoTo ConnectErr:
With Conn
.ConnectionString = connect_string
.Open
End With
ConnectErr:
If Err.Number <> 0 Then
MsgBox "There was an issue connecting to the Central DB."
Resume subexit
End If
On Error GoTo 0
''''''''''''''''''''''
' Starting the connection to DB
''''''''''''''''''''''
On Error GoTo QueryErr:
RS.Open SQL, Conn, adOpenStatic
QueryErr:
If Err.Number <> 0 Then
MsgBox "There was a problem with the Query. Could not get results from the statement:" & vbCrLf & Err.Description
dbArr = Array(" Failed Q ", " Failed Q ")
Resume subexit
End If
On Error GoTo 0
'''''''''''''''''''''
' Parse Data and fill array: DBarr
'''''''''''''''''''''
R = 0
#If VBA7 Then
Dim tmp_rowNum As LongPtr, tmp_colNum As LongPtr
Dim rowNum As Integer, colNum As Integer
tmp_rowNum = RS.RecordCount
tmp_colNum = RS.Fields.Count
rowNum = CLng(tmp_rowNum)
colNum = CLng(tmp_colNum)
#Else
Dim rowNum As Long, colNum As Long
rowNum = RS.RecordCount
colNum = RS.Fields.Count
#End If
If HasFields = 0 Then
ReDim dbArr(1 To rowNum + 1, 1 To colNum)
Else
ReDim dbArr(1 To rowNum + 2, 1 To colNum)
End If
Do While Not RS.EOF
R = R + 1
For C = 1 To RS.Fields.Count
If R = 1 And HasFields = 1 Then
dbArr(R, C) = RS.Fields(C - 1).Name
ElseIf Not R = 1 Then
dbArr(R, C) = RS.Fields(C - 1).Value
End If
Next
If Not R = 1 Then RS.MoveNext
Loop
subexit:
GetQuery = dbArr
Set Conn = Nothing
Set RS = Nothing
End Function
Next use the result of the Query (A [multi-dimensional] Array) to set the range in a worksheet:
Sub SetInitData()
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim sql_string As String, connect_String as String
Dim ws as Worksheet
Set ws = ThisWorkbook.Sheets(config.DATA_SHEET_NAME)
sql_string = config.GET_INITIAL_PACKTYPE_QUERY
connect_string = config.MAIN_CONNECTION_STRING
Debug.Print sql_string
Dim packtypedata As Variant
packtypedata = GetQuery(sql_string)
ws.Range(ws.Cells(1, 1), ws.Cells(UBound(packtypedata), UBound(packtypedata, 2))).Value = packtypedata
'' Keep Total Rows for next routine explained below
Dim total_rows as Integer
total_rows = UBound(packtypedata)
SetComboBoxValues(total_rows)
''' Turn on events and screen updating again
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Finally you want to set the ComboBox:
Sub SetComboBoxValues(total_rows As Integer)
Dim ws as Worksheet, data_ws as Worksheet
Dim data_arr as Variant
Dim pack_dd as DropDown
Set ws = ThisWorkbook.Sheets(config.INPUT_SHEET_NAME)
Set data_ws = ThisWorkbook.Sheets(config.DATA_SHEET_NAME)
data_arr = data_ws.Range(data_ws.Cells(1,config.DATA_COL_DROPDOWN_INDEX),
data_ws.Cells(total_rows,config.DATA_COL_DROPDOWN_INDEX)).Value
Set pack_dd = ws.Shapes(config.MAIN_DATA_DROPDOWN_NAME).OLEFormat.Object
pack_dd.List = pack_dd
''' To set the index
pack_dd.ListIndex = 1
End Sub
** Note -- The GetQuery function has some kinks that I haven't had time to work out, namely I don't think the HasFields option to include headers actually works.
Also I'm using DropDowns, so I'm not sure if you are using the same type of object.
Good Luck
I would like to loop through an Excel worksheet and to store the values based on a unique ID in a text file.
I am having trouble with the loop and I have done research on it with no luck and my current nested loop continually overflows. Instead of updating the corresponding cell when the control variable is modified, it continues to store the initial Index value for all 32767 iterations.
Please can someone explain why this is happening, and provide a way of correcting it?.
Sub SortLetr_Code()
'sort columns for Letr_Code files
Dim lr As Long
Application.ScreenUpdating = False
lr = Cells(Rows.Count, 1).End(xlUp).Row
Range("A2:B" & lr).Sort key1:=Range("B2"), order1:=1
Application.ScreenUpdating = True
'Value of cell for example B1 starts out as X
Dim x As Integer
Dim y As Integer
x = 2
y = 2
'Cell References
Dim rwCounter As Range
Dim rwCorresponding As Range
Dim rwIndexValue As Range
Dim rwIndexEnd As Range
Dim rwIndexStore As Range
'Variables for files that will be created
Dim FilePath As String
Dim Filename As String
Dim Filetype As String
'Variables defined
FilePath = "C:\Users\Home\Desktop\SURLOAD\"
Filetype = ".dat"
'Use Cell method for Loop
rwIndex = Cells(x, "B").Value
Set rwCounter = Range("B" & x)
'Use Range method for string manipulation
Set rwCorresponding = Range("A" & x)
Set rwIndexValue = Range("B" & y)
Set rwIndexStore = Range("B" & x)
Set rwIndexEnd = Range("B:B").End(xlUp)
'Objects for creating the text files
Dim FileCreate As Object
Set FileCreate = CreateObject("Scripting.FileSystemObject")
'Object for updating the file during the loop
Dim FileWrite As Object
For Each rwIndexStore In rwIndexEnd.Cells
'Get Substring of cell value in BX for the file name
Do Until IsEmpty(rwCounter)
Filename = Mid$(rwIndexValue, 7, 5)
Set FileWrite = FileCreate.CreateTextFile(FilePath + Filename + Filetype)
'Create the file
FileWrite.Write (rwCorresponding & vbCrLf)
Do
'Add values to the textfile
x = x + 1
FileWrite.Write (rwCorresponding & vbCrLf)
Loop While rwCounter.Value Like rwIndexValue.Value
'Close this file
FileWrite.Close
y = x
Loop
Next rwIndexStore
End Sub
I don't see a place you are setting rwCounter inside the loop.
It looks like it would stay on range("B2") and x would just continue to increase until it hits an error, either at the limit of integer or long.
add Set rwCounter = Range("B" & x) somewhere inside your loop to increment it
This is the solution.
Sub GURMAIL_File()
'sort columns for Letr_Code files
Dim lr As Long
Application.ScreenUpdating = False
lr = Cells(Rows.Count, 1).End(xlUp).Row
Range("A2:B" & lr).Sort key1:=Range("B2"), order1:=1
Application.ScreenUpdating = True
'Variables that store cell number
Dim Corresponding As Integer
Dim Index As Integer
Dim Counter As Integer
Corresponding = 2
Index = 2
Counter = 2
'Cell References
Dim rwIndexValue As Range
'Variables for files that will be created
Dim l_objFso As Object
Dim FilePath As String
Dim Total As String
Dim Filename As String
Dim Filetype As String
Dim FolderName As String
'Variables defined
FilePath = "C:\Users\Home\Desktop\SURLOAD\"
'Name of the folder to be created
FolderName = Mid$(ActiveWorkbook.Name, 9, 8) & "\"
'Folder path
Total = FilePath & FolderName
'File Extension
Filetype = ".dat"
'Object that creates the folder
Set l_objFso = CreateObject("Scripting.FileSystemObject")
'Objects for creating the text files
Dim FileCreate As Object
Set FileCreate = CreateObject("Scripting.FileSystemObject")
'Object for updating the file during the loop
Dim FileWrite As Object
'Get Substring of letter code in order to name the file. End this loop once ID field is null.
Do While Len(Range("A" & Corresponding)) > 0
'Create the directory if it does not exist
If Not l_objFso.FolderExists(Total) Then
l_objFso.CreateFolder (Total)
End If
'Refence to cell containing a letter code
Set rwIndexValue = Range("B" & Index)
'Substring of that letter code
Filename = Mid$(rwIndexValue, 7, 5)
'Create the file using the substring and store it in the proper location
Set FileWrite = FileCreate.CreateTextFile(Total + Filename + Filetype, True)
'For each letter code, find the corresponding values. End the loop once the last value for the letter code is stored.
Do While Range("B" & Index) Like Range("B" & Counter)
'Add each line to the text file.
FileWrite.WriteLine (Range("A" & Corresponding))
'Incrementer variables that allow you to exit the loop
'if you have reached the last value of the current letter code.
Corresponding = Corresponding + 1
Counter = Counter + 1
Loop
'Close the file you were writing to
FileWrite.Close
'Make sure that Index value is updated to the next letter code
Index = Counter
'In case Index value needs updating (safeguard to make sure that the new letter code is stored to index value).
Set rwIndexValue = Range("B" & Index)
Loop
End Sub