I have this code in a script task:
Public Sub Main()
'
' Add your code here
'
Dim MonthFromSQL As String
Dim lastMonth As New Date(DateTime.Today.Year, DateTime.Today.Month - 1, 1)
Dim rcnt As Integer
Dim msg As String
'MsgBox("Month name from SQL is " & CStr(Dts.Variables("MonthNameFromSQL").Value))
rcnt = CInt(Dts.Variables("RowCount").Value)
If rcnt = 0 Then
msg = "Job returned 0 rows for month " & CStr(MonthName(lastMonth.Month, False)) & " - check with database operator that previous month's data has been loaded into the database."
Else
msg = "Job returned " & rcnt & " rows - Job Finished"
End If
'Pass message variable value out to be used in message
Dts.Variables("EmailMessage").Value = msg
Dts.TaskResult = Dts.Results.Success
End Sub
If I modify the IF statement to below to be able to check the month value from SQL DB against system month value it gives me a DTS script error saying that:
The type of the value being assigned to variable "User::EmailMessage" differs from the current variable type. Variables may not change type during execution. Variable types are strict, except for variables of type Object.
'First check month name from sql match system last month name
If CStr(MonthName(lastMonth.Month, False)) = CStr(Dts.Variables("MonthNameFromSQL").Value) Then
MsgBox("Month name variable equals last month value")
If rcnt = 0 Then
msg = "Job returned 0 rows for month " & CStr(MonthName(lastMonth.Month, False)) & " - check with outpatient database operator that previous month's data has been loaded into the database."
Else
msg = "Job returned " & rcnt & " rows - Job Finished"
End If
Else
'Put in code to handle if month values do not match
End If
I replaced:
If CStr(MonthName(lastMonth.Month, False)) = CStr(Dts.Variables("MonthNameFromSQL").Value) Then
MsgBox("Month name variable equals last month value")
With:
If 1=1 Then
MsgBox("Month name variable equals last month value")
Just to check it would work with a simple comparing statement and that it was something to do with the code I had in the IF statement, as I did not suspect it was anything to do with the msg variable I was populating, even though this was the error message.
So I realise it is something to do with:
If CStr(MonthName(lastMonth.Month, False)) = CStr(Dts.Variables("MonthNameFromSQL").Value) Then
The montNameFromSQL is populated with the result set of a previous SQL task, and then in this script I am using it to check against the system month name. I want to check these values and if a match then success and move onto to check the rows returned, and populate the message to send in my email task.
Hopefully it's something simple and a fresh pair of eyes can spot!
Thanks
Andrew
Either you have the wrong data types assigned (which is what the error message is stating) or you have not faithfully reproduced your code.
I created a package with 3 variables.
EmailMessage: String -
MonthNameFromSQL: String - July
RowCount: Int32 - 0
I configured my "SCR Works fine" task to allow read access to the second two variables and read/write access to EmailMessage.
Inside the script, I used your code. I ran it with your original that works and the one that doesn't work for you.
Public Sub Main()
Dim MonthFromSQL As String
Dim lastMonth As New Date(DateTime.Today.Year, DateTime.Today.Month - 1, 1)
Dim rcnt As Integer
Dim msg As String
'MsgBox("Month name from SQL is " & CStr(Dts.Variables("MonthNameFromSQL").Value))
rcnt = CInt(Dts.Variables("RowCount").Value)
'If rcnt = 0 Then
' msg = "Job returned 0 rows for month " & CStr(MonthName(lastMonth.Month, False)) & " - check with database operator that previous month's data has been loaded into the database."
'Else
' msg = "Job returned " & rcnt & " rows - Job Finished"
'End If
'First check month name from sql match system last month name
If CStr(MonthName(lastMonth.Month, False)) = CStr(Dts.Variables("MonthNameFromSQL").Value) Then
MsgBox("Month name variable equals last month value")
If rcnt = 0 Then
msg = "Job returned 0 rows for month " & CStr(MonthName(lastMonth.Month, False)) & " - check with outpatient database operator that previous month's data has been loaded into the database."
Else
msg = "Job returned " & rcnt & " rows - Job Finished"
End If
Else
'Put in code to handle if month values do not match
msg = "I am here"
End If
'Pass message variable value out to be used in message
Dts.Variables("EmailMessage").Value = msg
Dts.TaskResult = ScriptResults.Success
End Sub
As you can see from the value of the EmailMessage variable, it's populated and the script has completed.
This package is using SQL Server 2012 but the fundamentals of what you are trying has been available since 2005.
Integration Services (SSIS) Variables
Using Variables in the Script Task
only issue I see is with the data type of MonthNameFromSQL variable, somehow MonthNameFromSQL is assigned wrong data type or its getting null value.
I will recommend you to do the following.
Ensure that date_column datetime field in your table is NOT NULLABLE or Do null check in your sql statement to ensure that it is not passing any null values to the MonthNameFromSQL variable.
select distinct ISNULL(convert(varchar(12),(datename(month, date_column))), '') as monthName FROM dbo.table1
Delete the MonthNameFromSQL varialble from variablbe window(shown on
the left pane in visual studio), recreate this variable again
ensuring that scope of the variable is at package level and data
type is string type. select this variable from result set of execute
sql task properties.
If above step fails, recreate package freshly.
Related
I apologize for the long post but I'm losing my mind here. I've tried looking this up but I keep getting error messages on any suggested fixes on this thread:
SSRS distinct lookupset function
I've even tried to completely recreate a similar data set in that question but keep getting issues.
This is the data set I created.
Using this in the expression box, and grouping by itemID, rackID, UseByDate
Join(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!CustomerSeqNo.Value
, "PickingList"), ",")
I get
but I would like to remove the duplicates in the LookupSet so it would just display "1".
I tried the first 2 options in that link above but they both provided an error message:
Public Shared Function RemoveDuplicates(m_Array As Object()) As String()
System.Array.Sort(m_Array)
Dim k As Integer = 0
For i As Integer = 0 To m_Array.Length - 1
If i > 0 AndAlso m_Array(i).Equals(m_Array(i - 1)) Then
Continue For
End If
m_Array(k) = m_Array(i)
k += 1
Next
Dim unique As [String]() = New [String](k - 1) {}
System.Array.Copy(m_Array, 0, unique, 0, k)
Return unique
End Function
with this expression:
=Join(Code.RemoveDuplicates(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!CustomerSeqNo.Value
, "PickingList")), ",")
returns this warning:
[rsRuntimeErrorInExpression] The Value expression for the textrun 'CustomerSeqNo.Paragraphs[0].TextRuns[0]' contains an error: Operator '&' is not defined for type 'Integer' and type 'CalculatedFieldWrapperImpl'. and this error
The other solution doesn't even deploy. Any help here?
Luckily for you #JMG, I just had to do this for a customer!
Here's the function:
public function DistinctValues(input() as Object) as string
dim newList as String
for each n as string in input
if InStr(newList, cstr(n) + ", ") = false
newList += cstr(n) + ", "
end if
next
return left(newList, len(newList) -2)
end function
So what it's doing is parsing through each value in the array. We are going to insert each unique value into a comma delimited string. Before doing so, we just check the string with InStr to see if that value already exists.
Make sure you cast the return value to string via CSTR(Fields!CustomerSeqNo.Value) to avoid any datatype issues. Your code should look something like this.
Code.DistinctValues(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value, CSTR(Fields!CustomerSeqNo.Value), "PickingList"))
A colleague of mine has created a program that reads a text file and assigns various values from it to variables that are used in SQL statements.
One of these variables, gsAccounts is a string variable.
Using a string builder, a SELECT statement is being built up with sql.append. At the end of the string, there is the following line:
sql.Append(" WHERE L.Account_Code IN(" & gsAccounts & ")"
The problem that I'm having is that sometimes, not always, gsAccounts (a list of account codes) may contain an account code with an apostrophe, so the query becomes
"WHERE L.Account_Code IN('test'123')"
when the account code is test'123
I have tried using double quotes to get around it in a "WHERE L.Account_Code IN("""" & gsAccounts & """")" way (using 4 and 6 " next to each other, but neither worked)
How can I get around this? The account_Code is the Primary Key in the table, so I can't just remove it as there are years worth of transactions and data connected to it.
I posted the following example here 10 years ago, almost to the day. (Oops! thought it was Jun 5 but it was Jan 5. 10.5 years then.)
Dim connection As New SqlConnection("connection string here")
Dim command As New SqlCommand
Dim query As New StringBuilder("SELECT * FROM MyTable")
Select Case Me.ListBox1.SelectedItems.Count
Case 1
'Only one item is selected so we only need one parameter.
query.Append(" WHERE MyColumn = #MyColumn")
command.Parameters.AddWithValue("#MyColumn", Me.ListBox1.SelectedItem)
Case Is > 1
'Multiple items are selected so include a parameter for each.
query.Append(" WHERE MyColumn IN (")
Dim paramName As String
For index As Integer = 0 To Me.ListBox1.SelectedItems.Count - 1 Step 1
'Name all parameters for the column with a numeric suffix.
paramName = "#MyColumn" & index
'Add a comma before all but the first value.
If index > 0 Then
query.Append(", ")
End If
'Append the placeholder to the SQL and add the parameter to the command
query.Append(paramName)
command.Parameters.AddWithValue(paramName, Me.ListBox1.SelectedItems(index))
Next index
query.Append(")")
End Select
command.CommandText = query.ToString()
command.Connection = connection
Single quotes can be "escaped" by making them double single quotes. E.g. ' becomes ''.
However this approach is generally not recommended due to the high risk of SQL injection - a very dangerous and prevalent issues. See: https://www.owasp.org/index.php/SQL_Injection
To avoid this most libraries will include some type of escaping mechanism including the use of things like prepared statements in the Java world. In the .net world this may be of use: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.prepare(v=vs.110).aspx
If you only have one with a field, this is the easiest solution
Private Function gsAccountsConvert(ByVal gsAccounts As String)
Dim gsAccountsString As String = ""
Dim StringTemp
StringTemp = gsAccounts.Split(",")
Dim i As Integer
For i = 0 To UBound(StringTemp)
StringTemp(i) = StringTemp(i).ToString.Trim
If StringTemp(i) <> "" Then
If StringTemp(i).ToString.Substring(0, 1) = "'" Then
StringTemp(i) = """" & StringTemp(i).ToString.Substring(1, Len(StringTemp(i).ToString) - 2) & """"
End If
End If
If i <> UBound(StringTemp) Then
gsAccountsString = gsAccountsString & StringTemp(i).ToString.Replace("'", "''") & ","
Else
gsAccountsString = gsAccountsString & StringTemp(i).ToString.Replace("'", "''") & ""
End If
Next
gsAccountsString = gsAccountsString.Replace("""", "'")
Return gsAccountsString
End Function
I'm creating a database on Excel, and encountered some problems as I tried to assign auto number to each row.
Requirements are:
generate auto number to each row(on the column A) when column B is not blank.
the number should be unique and must always be connected to the contents of the same row even when the column is sorted or when new rows are inserted, etc.
when a new row is inserted (anywhere on the same column), a new number should be assigned (the newest number should be the biggest number)
if
possible, the auto number should have a prefix, and number should be displayed in four digits (e.g. 0001, 0011)
I have tried some VBA codes I found from other people's questions (e.g. Excel VBA : Auto Generating Unique Number for each row).
So far, the code below has worked the best, but the requirement (3) and (4) couldn't be solved by that code.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim maxNumber
If Not Intersect(Target, Range("B:B")) Is Nothing Then
' don't run when more than one row is changed
If Target.Rows.Count > 1 Then Exit Sub
' if column A in the current row has a value, don't run
If Cells(Target.Row, 1) > 0 Then Exit Sub
' get the highest number in column A, then add 1 and write to the
' current row, column A
maxNumber = Application.WorksheetFunction.Max(Range("A:A"))
Target.Offset(0, -1) = maxNumber + 1
End If
End Sub
I'm short of the knowledge of VBA and I hope someone could help me this.
Many thanks.
Alternative via CustomDocumentProperties
Instead of using a hidden sheet as proposed by #TimWilliams, one can assign incremented values to a user defined custom document property (CDP), naming it e.g. "InvNo" holding the newest invoice number. The cdp remain stored in the saved workbook.
The function below gets the current number saved to this workbook related property and returns the next number by adding 1 to the current value. It uses a help procedure RefreshCDP to assign the new value (could be used of course independantly to reset values programmaticaly to any other value). - If the cdp name isn't passed as (optional) argument, the function assumes "InvNo" by default.
Note that code requires some error handling to check if the cdp exists.
Example call
Dim InvoiceNumber as Long
InvoiceNumber = NextNumber("InvNo") ' or simply: NextNumber
Public Function NextNumber(Optional CDPName As String = "InvNo") As Long
'a) get current cdp value
Dim curVal As Long
On Error Resume Next
curVal = ThisWorkbook.CustomDocumentProperties(CDPName)
If Err.Number <> 0 Then Err.Clear ' not yet existing, results in curVal of 0
'b) increment current cdp value by one to simulate new value
Dim newVal As Long
newVal = curVal + 1
'Debug.Print "Next " & CDPName & " will be: " & newVal
'c) assign new value to custom document property
RefreshCDP CDPName, newVal, msoPropertyTypeNumber
'Debug.Print "New " & CDPName & " now is: " & ThisWorkbook.CustomDocumentProperties(CDPName)
NextNumber = newVal
End Function
Help procedure RefreshCDP
Sub RefreshCDP(CDPName As String, _
newVal As Variant, docType As Office.MsoDocProperties)
On Error Resume Next
ThisWorkbook.CustomDocumentProperties(CDPName).Value = newVal
'If cdp doesn't exist yet, create it (plus adding the new value)
If Err.Number > 0 Then
ThisWorkbook.CustomDocumentProperties.Add _
Name:=CDPName, _
LinkToContent:=False, _
Type:=docType, _
Value:=newVal
End If
End Sub
Related links
MS help: Excel.Workbook.CustomDocumentProperties
Check if BuiltInDocumentProperty is set without error trapping
Chip Pearson: Document Properties
How to add a DocumentProperty to CustomDocumentProperties in Excel?
Do not use Max() to find the next number - use instead a hidden sheet or name to store the current number, and increment it each time a new Id is required.
For example:
Public Function NextNumber(SequenceName As String)
Dim n As Name, v
On Error Resume Next
Set n = ThisWorkbook.Names(SequenceName)
On Error GoTo 0
If n Is Nothing Then
'create the name if it doesn't exist
ThisWorkbook.Names.Add SequenceName, RefersTo:=2
v = 1
Else
'increment the current value
v = Replace(n.RefersTo, "=", "")
n.RefersTo = v + 1
End If
NextNumber = v
End Function
This allows you to use multiple different sequences as long as you give each one a distinct name.
Dim seq
seq = NextNumber("seqOne")
'etc
I have block of code where I'm using a For... Next loop to go through an Excel sheet, and tell me if values entered in the text boxes were found or not. I've modified it to work if the values match. Yet, I'm receiving the Object/With Block variable not set error, and it confusing me. I've created the following:
Dim Value2Find_1 As String = txtMachNumber.Text 'Serial number value.
Dim Value2Find_2 As String = txtMachName.Text 'Machine name value.
Dim ReplaceWithValue1 As String = "" 'Replaces the serial number value if found in the sheet.
Dim ReplaceWithValue2 As String = "" 'Replaces the machine name value if found in the sheet.
Dim ReplaceWithValue3 As String = "" 'Replacement for the date-time in the Date Column.
Dim Range2Use_1 = xlWS.Range("A1:A4000") 'Range to span the A Column.
Dim Range2Use_2 = xlWS.Range("B1:B4000") 'Range to span the B Column.
Dim Range2Use_3 = xlWS.Range("F1:F4000") 'Range to span the F Column.
Dim xlCell_A = Range2Use_1.Find(txtMachNumber.Text) 'Looks up the searched serial value in A Column.
Dim xlCell_B = Range2Use_2.Find(txtMachName.Text) 'Looks up the searched machine value in B Column.
Dim LastRow = xlWS.Range("A4000").End(Excel.XlDirection.xlUp).Row + 1
Dim i As Integer
With xlWS
For i = 1 To LastRow
If Not (Value2Find_1 = txtMachNumber.Text And Value2Find_2 = txtMachName.Text) Then
MessageBox.Show("No value exists here...")
Else
Range2Use_1.Find(What:=Value2Find_1, MatchCase:=True)
Range2Use_2.Find(What:=Value2Find_2, MatchCase:=True)
MsgBox("Found both values: " & Value2Find_1 & " and " & Value2Find_2 & " on row " & xlCell_A.Row)
End If
Exit Sub
Next
End With
If my textbox entries are not in the sheet, the errors returns on the following line of code:
MsgBox("Found both values: " & Value2Find_1 & " and " & Value2Find_2 & " on row " & xlCell_A.Row)
I've narrowed it down to have something to do with the variable that returns the row number of the located textbox entries - xlCell_A. This is where I'm stuck, however. What do I need to set this as in order to avoid the Object/With Block variable not set error? I am afraid I don't know what this is asking for.
I think the problem with your code is that the Find method returns Nothing whenever no match is found, as stated in its documentation. Thus, xlCell_A.Row returns the error because the Row method cannot be called on Nothing.
Actually, I see a number of further issues with your code:
The interior of the for loop does not depend on the loop variable i. Hence, it does exactly the same thing in each interation.
The variable xlWS of the With block is never used, which makes the With block unnessesary.
The return values of the Find methods in the loop never gets assigned to anything. Because of this, they have no effect.
The condition in the if statement always returns False since you never change the values of Value2Find_1 and Value2Find_2 and you initialized them to txtMachNumber.Text and txtMachName.Text, respectively.
If you intend to evaluate whether the values txtMachNumber.Text and txtMachName.Text are present in the column A and B, respectively, you can just test whether xlCell_A and xlCell_B are Nothing.
Since you want to find both on the same row, which using Find does not guarantee, it might be easier to use a loop as in your code but replace
txtMachNumber.Text and txtMachName.Text with Range2Use_1.Cells(i,1) and Range2Use_2.Cells(i,1) in the if statement. (This compares the value in the ith row with the values to search for.) Obviously, you would have to exit the loop after finding a match, e.g. using the break statement.
I am building a reconciliation tool via VBA that automates queries from my oracle database and a worksheet. When I run the query I want the user to input what ITEM (in this case pipeline) to query (the worksheet has many items) and the end/start dates. I am having trouble figuring out the following:
1) It is querying - if the value is NULL, how may I tell it to print out "DATA NOT AVAILABLE"
2) How can I clear up the old output from pipeline A, when I am querying pipeline B?
3) My dates are saved as strings in Oracle - how can I convert that to date?
Thank you!
Here is what I have so far:
Option Explicit
Option Base 1
Dim cnnObject As ADODB.Connection
Dim rsObject As ADODB.Recordset
Dim strGPOTSConnectionString As String
Dim startDate As Date
Dim endDate As Date
Dim strPipelineName As String
Dim strQuery As String
Sub ClickButton2()
Debug.Print ("Button has been clicked")
Dim Pipeline As String
Dim DateStart As Date
Dim DateEnd As Date
Pipeline = InputBox("Enter PipeLine", "My Application", "Default Value")
DateStart = InputBox("Enter Start Date", "My Application", DateTime.Date)
DateEnd = InputBox("Enter End Date", "My Application", DateTime.Date + 1)
Pipeline = Range("B1").Value
DateStart = Range("B2").Value
DateEnd = Range("B3").Value
strQuery = "select pipelineflow.lciid lciid, ldate, volume, capacity, status, " & _
"pipeline, station, stationname, drn, state, county, owneroperator, companycode, " & _
"pointcode, pottypeind, flowdirection, pointname, facilitytype, pointlocator, " & _
"pidgridcode from pipelineflow, pipelineproperties " & _
"where pipelineflow.lciid = piplineproperties.lciid " & _
"and pipelineflow.audit_active = 1 " & _
"and pipelineproperties.audit_active =1 " & _
"and pipelineflow.ldate >= '" & Format(DateStart, "dd-MMM-yyyy") & "' and pipelineflow.ldate < '" & Format(DateEnd, "dd-MMM-yyyy") & "' " & _
"and pipelineflow.ldate >= '" & DateStart & "' and pipelineflow.ldate < '" & DateEnd & "' " & _
"and pipelineproperties.pipeline = '" & Pipeline & "' "
Call PullZaiNetData(strQuery)
Call TieOut
End Sub
Sub PullZaiNetData2(ByVal strQry As String)
Set cnnObject = New ADODB.Connection
Set rsObject = New ADODB.Recordset
strGPOTSConnectionString = "DRIVER={Microsoft ODBC for Oracle}; SERVER=hhh; PWD=hhhh; UID=hhh"
cnnObject.Open strGPOTSConnectionString
rsObject.Open strQry, cnnObject, adOpenStatic
Worksheets("ZaiNet Data").Cells(1, 1).CopyFromRecordset rsObject
rsObject.Close
cnnObject.Close
Set rsObject = Nothing
Set cnnObject = Nothing
End Sub
Sub TieOut()
End Sub
Since you changed your questions, I'll add another answer.
1) It is querying - if the value is NULL, how may I tell it to print out "DATA NOT AVAILABLE"
Which value? I suspect that you mean when the query returns no records. To check this, test for rsObject.RecordCount = 0:
Dim ws As Worksheet
Set ws = Worksheets("ZaiNet Data")
ws.UsedRange.Clear '' remove results of previous query if any
If rsObject.RecordCount = 0 Then
ws.Cells(1, 1) = "DATA NOT AVAILABLE"
Else
ws.Cells(1, 1).CopyFromRecordset rsObject
End If
You can also test for one or both of rsObject.BOF or rsObject.EOF being true ("Beginning Of File" or "End Of File" respectively).
When developing things in VBA, especially when using new features that I'm unfamiliar with, I do lots of tests that output things to the Immediate Window. To help with this, I use the following little routine:
Sub Say(s as String)
Debug.Print s
End Sub
It makes it a little easier to generate testing output that typing "Debug.Print" all the time (even slightly easier than typing "Debug.P" + Enter using Intellisense).
So when you open your recordset, show the record count after it:
rsObject.Open strQry, cnnObject, adOpenStatic
Say rsObject.RecordCount & " records"
Do something like this any time you want to verify a value.
Later on, if you want to capture your debugging statements in a text file, you just need to change the operation of the Say() routine.
2) How can I clear up the old output from pipeline A, when I am querying pipeline B?
As shown in context above:
ws.UsedRange.Clear '' remove results of previous query if any
3) My dates are saved as strings in Oracle - how can I convert that to date?
You don't technically need to convert the resulting date strings to date values, you may find that just by putting them in a cell, Excel will treat them as date values.
You just need to make sure that the user's dates get converted to the format that the database is expecting.
Your query string as it stands above still shows two lines incorporating the user's dates. The one that uses Format() to convert them to "dd-MMM-yyyy" format is the one you want to keep. Delete the other line, making sure your string concatenating syntax is still correct.
To actually convert the date string to a date value though, you would use the CDate() function:
Sub DateTest()
Dim sDate As String
Dim dDate As Date
sDate = "09-Jul-2009"
dDate = CDate(sDate)
Say "sDate = " & sDate
Say "dDate = " & dDate
dDate = dDate + 1
Say "dDate = " & dDate
End Sub
Immediate Window output:
sDate = 09-Jul-2009
dDate = 7/9/2009
dDate = 7/10/2009
We can verify that it converted the string to a date value because it shows up in the default date format for my machine, and responds to date math (adding 1 day).
Answers to previous questions (paraphrased):
1) "how to make sure end date is after start date":
Valid date values are floating point numbers, so DateEnd should be >= DateStart. The whole number part is the number of days since 1900-01-01. The fractional part is the current time of day (eg 12 noon = 0.5).
2) "use fancy calendar entry controls for dates"
Look at the controls available under the Insert> Object menu (in Excel 2003 and earlier - it's in 2007 too, but in a different place). One of them is a Calendar control. Double-clicking it in the Objects list will insert it into the current cell and put the sheet into Design Mode. Right click the control and choose Properties. Type a cell address into the LinkedCell field. Then click the "Exit Design Mode" button from the little toolbar that should have popped up. Now when you select a date on the control, it will show the value in the cell you linked it to.
Similarly there is a drop down list control that you can use to select your pipeline types.
3) "why am I getting an error on DateEnd = Range("B3").Value?"
The DateEnd error is probably due to a missing or invalid value in the cell you specified, as I asked in my comment.
What version of Excel are you doing this in? Excel 2003