You are on page 1of 20

Imports Infragistics.

Excel
Imports System.Data
Imports System.Data.SqlClient
Imports DocumentFormat.OpenXml
Public Class ExcelOperations
Dim arImportErrors As ImportException() = {}
Dim arWorksheets() As CitishareWorksheetConfiguration = {}
'Local collections to store Lookup values. Collections instead of arrays so
we can reference without iteration.
Dim colRegions As New Collection
Dim colLocationTypes As New Collection
Dim colFacilityTypes As New Collection
Dim colBranchAccessibility As New Collection
Dim colBranchServices As New Collection
Dim colLanguages As New Collection
Dim colHourTypes As New Collection
Dim colOwners As New Collection
Dim colTitles As New Collection
Dim colTerminalVendorServices As New Collection
Dim colTerminalServices As New Collection
Dim colBranchIDs As New Collection
Dim colTerminalIDs As New Collection
Dim colBrandingConfigs As New Collection
Public Enum ExportDatasetTable
WorksheetNames = 0
Branches = 1
End Enum
Public ReadOnly Property ImportErrors As ImportException()
Get
Return arImportErrors
End Get
End Property
''' <summary>
''' This sub will generate an excel workbook containing the specified group'
s data and output it using a naming convention.
''' </summary>
''' <param name="GroupID"></param>
''' <param name="CN"></param>
''' <remarks></remarks>
Public Sub GenerateExcelTemplate(ByVal GroupID As Integer, ByVal CN As SqlCo
nnection, FileName As String)
'Get the data into a dataset to represent the exportable group data....
Dim sda As SqlDataAdapter = Nothing
Dim strCurrentWorksheetName As String = ""
Try
sda = New SqlDataAdapter("", CN)
sda.SelectCommand.CommandText = "mgmt.ExportTemplate"
sda.SelectCommand.CommandType = CommandType.StoredProcedure
sda.SelectCommand.Parameters.Clear()
sda.SelectCommand.Parameters.AddWithValue("GroupID", GroupID)
Dim dsExportData As New DataSet
sda.Fill(dsExportData)
Dim objExcelWorkbook As New Infragistics.Excel.Workbook(WorkbookForm

at.Excel97To2003)
objExcelWorkbook.CellReferenceMode = CellReferenceMode.R1C1 'Set the
reference mode to Row/Column rather than alpha to more closely align to dataset
s/tables
Dim intTableCounter As Integer = 1 'Start at 1 since index 0 is the
sheet name records
Dim colIgnoreColumns As New Specialized.StringCollection
colIgnoreColumns.Add("group_id")
If dsExportData.Tables.Count <> dsExportData.Tables(ExportDatasetTab
le.WorksheetNames).Rows.Count + 1 Then
Throw New Exception("The number of worksheets expected [" & dsEx
portData.Tables(ExportDatasetTable.WorksheetNames).Rows.Count + 1 & "] does not
match the number of datasets returned [" & dsExportData.Tables.Count & "]")
End If
'The first datatable should represent the names we would like the wo
rksheets to be. They should be in the order of the worksheets to come.
For Each drWorksheetName As DataRow In dsExportData.Tables(ExportDat
asetTable.WorksheetNames).Rows
'Create new worksheet
strCurrentWorksheetName = drWorksheetName("worksheet_name").ToSt
ring()
Dim objCurrentWorksheet As Worksheet = objExcelWorkbook.Workshee
ts.Add(drWorksheetName("worksheet_name").ToString())
Dim objWorksheetConfig As New CitishareWorksheetConfiguration(dr
WorksheetName("worksheet_name").ToString(), CN)
objCurrentWorksheet.Protected = True
'Populate the worksheet
'The index of the data table we are interested in should be + 1
from the current worksheet record
Dim dtCurrentTable As DataTable = dsExportData.Tables(intTableCo
unter)
Dim intColumnCounter As Integer = 0
Dim intRowCounter As Integer = 0
'First write out all the column headings
For Each colExportColumn As CitishareWorksheetConfiguration.Citi
shareWorksheetColumn In objWorksheetConfig.Columns
If colExportColumn.ExportColumn Then
If colExportColumn.HyperlinkAddress <> "" Then
'We are adding a column header that has a hyperlink
objCurrentWorksheet.Rows
(intRowCounter).Cells(intColumnCounter).ApplyFormula("=HYPERLINK(""#"" & CELL(""
address"", " & colExportColumn.HyperlinkAddress & "),""" & colExportColumn.Expor
tColumnName & """)")
objCurrentWorksheet.Rows(intRowCounter).Cells(intCol
umnCounter).CellFormat.Font.Color = System.Drawing.Color.Blue
'We will tag the comment with the column name for va
lidation later. We have to do this since hyperlinks lose their value...
objCurrentWorksheet.Rows(intRowCounter).Cells(intCol
umnCounter).Comment = New WorksheetCellComment()
objCurrentWorksheet.Rows(intRowCounter).Cells(intCol
umnCounter).Comment.Text.UnformattedString = colExportColumn.ExportColumnName
Else
objCurrentWorksheet.Rows(intRowCounter).Cells(intCol
umnCounter).Value = colExportColumn.ExportColumnName

End If
If colExportColumn.ColumnFormat <> "" Then
objCurrentWorksheet.Columns(intColumnCounter).CellFo
rmat.FormatString = colExportColumn.ColumnFormat
End If
If colExportColumn.ColumnIsReadonly = ExcelDefaultableBo
olean.True Then
objCurrentWorksheet.Columns(intColumnCounter).CellFo
rmat.FillPatternForegroundColor = Drawing.Color.LightGray
End If
objCurrentWorksheet.Rows(intRowCounter).Cells(intColumnC
ounter).CellFormat.Font.Bold = ExcelDefaultableBoolean.True
objCurrentWorksheet.Columns(intColumnCounter).Width = co
lExportColumn.ColumnWidth
intColumnCounter += 1
End If
Next
'Now write all the data out.
intRowCounter = 0
For Each drDataRecord As DataRow In dtCurrentTable.Rows
intRowCounter += 1
intColumnCounter = 0
For Each colExportColumn As CitishareWorksheetConfiguration.
CitishareWorksheetColumn In objWorksheetConfig.Columns
If colExportColumn.ExportColumn Then
'Determine the type. We may need to map from SQL to
Excel
Select Case drDataRecord(colExportColumn.DatasourceC
olumnName).GetType.Name.ToLower()
Case "timespan"
'No comp
atible datatype in Excel for TimeSpan
Dim strT
imeValue As String = drDataRecord(colExportColumn.DatasourceColumnName).ToString
()
Try
If strTimeValue <> "" Then
If IsDate(strTimeValue) Then
strTimeValue = String.Format("{0:hh:mm tt}", CDate(strTimeValue))
End If
End If
Catch ex
As Exception
'Swallow error. Fall back on value
End Try
objCurre
ntWorksheet.Rows(intRowCounter).Cells(intColumnCounter).Value = strTimeValue
Case Else

objCurrentWorksheet.Rows(intRowCounter).Cell
s(intColumnCounter).Value = drDataRecord(colExportColumn.DatasourceColumnName)
End Select
If colExportColumn.ColumnIsReadonly = ExcelDefaultab
leBoolean.True Then
'WE lock all cells instead of columns so users c
an add additional records if they like.
objCurrentWorksheet.Rows(intRowCounter).Cells(in
tColumnCounter).CellFormat.Locked = colExportColumn.ColumnIsReadonly
End If
intColumnCounter += 1
End If
Next
Next
'Since we have protected the worksheet, we need to unlock rows t
o allow for additional records to be created.
'We will unlock 1000 rows over whatever we exported
For intUnlockCounter As Integer = (intRowCounter + 1) To (intRow
Counter + 1000)
objCurrentWorksheet.Rows(intUnlockCounter).CellFormat.Locked
= ExcelDefaultableBoolean.False
Next
'Lock the first column and row
objCurrentWorksheet.DisplayOptions.PanesAreFrozen = True
If objWorksheetConfig.NumberOfFrozenColumns > 0 Then
objCurrentWorksheet.DisplayOptions.FrozenPaneSettings.Frozen
Columns = objWorksheetConfig.NumberOfFrozenColumns
End If
objCurrentWorksheet.DisplayOptions.FrozenPaneSettings.FrozenRows
= 1
intTableCounter += 1
Next
objExcelWorkbook.Save(FileName)
Catch ex As Exception
My.Application.Log.WriteException(ex, Diagnostics.TraceEventType.Err
or, "An error occurred in GenerateExcelTemplate(); Worksheet: [" & strCurrentWor
ksheetName & "]" & vbCrLf & ex.StackTrace.ToString())
Throw ex
Finally
sda.Dispose()
End Try
End Sub
''' <summary>
''' This sub will open an excel workbook, expecting it to be setup as a temp
late generated above.
''' It will validate the schema, and then validate the data to be loaded.
''' Depending on the group's configuration, the data will be loaded into sta
ging or directly into production
''' </summary>
''' <param name="UserID"></param>
''' <param name="CN"></param>
''' <remarks></remarks>

Public Sub ImportExcelTemplate(UserID As Integer, UploadID As Integer, CN As


SqlConnection)
Dim strPathToTemplate As String = ""
'Step 1 is to reset the upload information
Dim bUploadError As Boolean = True
Dim scmd As New SqlCommand("", CN)
Dim sda As New SqlDataAdapter("", CN)
Dim GroupID As Integer = 0
Try
If scmd.Connection.State <> ConnectionState.Open Then
scmd.Connection.Open()
End If
sda.SelectCommand.CommandType = CommandType.StoredProcedure
sda.SelectCommand.CommandText = "[mgmt].[GetUploads]"
sda.SelectCommand.Parameters.Clear()
sda.SelectCommand.Parameters.AddWithValue("UserID", UserID)
sda.SelectCommand.Parameters.AddWithValue("UploadID", UploadID)
Dim dtUpload As New DataTable
sda.Fill(dtUpload)
Dim drUploadInfo As DataRow = dtUpload.Rows(0)
strPathToTemplate = drUploadInfo("upload_path")
GroupID = drUploadInfo("group_id")
dtUpload.Dispose()
If My.Computer.FileSystem.FileExists(strPathToTemplate) = False Then
Throw New Exception("The path [" & strPathToTemplate & "] does n
ot exist.")
End If
'Now try and open up the template
Dim objExcelWorkbook As Infragistics.Excel.Workbook = Infragistics.E
xcel.Workbook.Load(strPathToTemplate)
objExcelWorkbook.CellReferenceMode = CellReferenceMode.R1C1 'Set the
reference mode
'Get all the worksheets and columns we should have...
Dim dtWorksheetsExpected As New DataTable
sda.SelectCommand.CommandType = CommandType.Text
sda.SelectCommand.CommandText = "SELECT * FROM mgmt.export_worksheet
s ORDER BY Ordinal"
sda.Fill(dtWorksheetsExpected)
Array.Resize(arWorksheets, dtWorksheetsExpected.Rows.Count)
Dim intWorksheetCounter As Integer = 0
For Each drWorksheet As DataRow In dtWorksheetsExpected.Rows
arWorksheets(intWorksheetCounter) = New CitishareWorksheetConfig
uration(drWorksheet("worksheet_name"), CN)
intWorksheetCounter += 1
Next
If ValidateWorkbookSchema(objExcelWorkbook) = False Then
Throw New Exception("Import Failed. The schema of the workbook d
oes not match the required template.")
End If

'At this point we have validated the schema of the workbook.


'Now get all the possible values for lookups we may encounter.
'We will store them in collections so we can easily validate supplie
d data
'We cannot do this until the workbook schema is validated!
LoadLookupCollections(scmd, GroupID)
If ValidateData(objExcelWorkbook) = False Then
Throw New Exception("Import Failed. The data provided in the wor
kbook is not valid. Please review the errors.")
End If
If LoadData(scmd, GroupID, UploadID, UserID) = False Then
Throw New Exception("Import Failed. Upload failed during the dat
a load phase.")
End If
Catch ex As Exception
My.Application.Log.WriteException(ex, TraceEventType.Error, "An unha
ndled exception has occurred!" & vbCrLf & ex.StackTrace)
Throw
Finally
'Log the result
'Cleanup
sda.Dispose()
End Try
End Sub
Public Sub LoadLookupCollections(CMD As SqlCommand, GroupID As Integer)
FillCollection(colRegions, "SELECT region_id FROM dbo.REGIONS WHERE grou
p_id = " & GroupID, CMD)
FillCollection(colBranchAccessibility, "SELECT accessibility_id FROM dbo
.lkup_accessibility", CMD)
FillCollection(colBranchServices, "SELECT br_serviceid FROM dbo.br_servi
ces", CMD)
FillCollection(colLanguages, "SELECT language_id FROM dbo.lkup_languages
", CMD)
FillCollection(colHourTypes, "SELECT hour_type_id FROM dbo.lkup_hour_typ
es", CMD)
FillCollection(colTitles, "SELECT title_id FROM dbo.lkup_titles", CMD)
FillCollection(colTerminalVendorServices, "SELECT vndr_service_id FROM d
bo.lkup_vnd_services", CMD)
FillCollection(colTerminalServices, "SELECT tm_serviceid FROM dbo.tm_ser
vices", CMD)
FillCollection(colLocationTypes, "SELECT location_typeid FROM db
o.lkup_location_type", CMD)
FillCollection(colFacilityTypes, "SELECT facility_type_id FROM d
bo.lkup_facility_types", CMD)
FillCollection(colOwners, "SELECT owner_id FROM dbo.lkup_owners"
, CMD)
FillCollection(colBrandingConfigs, "SELECT branding_config_id FR
OM dbo.branding_config", CMD)
'Load all the possible branchs from the worksheet

Dim objBranchSheet As CitishareWorksheetConfiguration = arWorksheets(Get


WorksheetIndex("Branches"))
Dim intRowCounter As Integer = 1
Dim intColumnIndex As Integer = GetColumnIndex("Location ID", objBranchS
heet)
If intColumnIndex < 0 Then
Throw New Exception("[Location ID] column could not be found in the
worksheet configuration passed!;")
End If
Dim tmpCell As WorksheetCell = objBranchSheet.WorksheetObject.Rows(intRo
wCounter).Cells(intColumnIndex)
Do While intRowCounter < 10000 And (IsNothing(tmpCell.Value) = False And
Also tmpCell.Value.ToString() <> "")
intRowCounter += 1
colBranchIDs.Add(tmpCell.Value, tmpCell.Value)
tmpCell = objBranchSheet.WorksheetObject.Rows(intRowCounter).Cells(i
ntColumnIndex)
Loop
'Load all possible terminal ids from the worksheet
Dim objTerminalSheet As CitishareWorksheetConfiguration = arWorksheets(G
etWorksheetIndex("Terminals"))
intRowCounter = 1
intColumnIndex = GetColumnIndex("Terminal ID", objTerminalSheet)
If intColumnIndex < 0 Then
Throw New Exception("[Terminal ID] column could not be found in the
worksheet configuration passed!;")
End If
tmpCell = objTerminalSheet.WorksheetObject.Rows(intRowCounter).Cells(int
ColumnIndex)
Do While intRowCounter < 10000 And (IsNothing(tmpCell.Value) = False And
Also tmpCell.Value <> "")
intRowCounter += 1
colTerminalIDs.Add(tmpCell.Value, tmpCell.Value)
tmpCell = objTerminalSheet.WorksheetObject.Rows(intRowCounter).Cells
(intColumnIndex)
Loop
End Sub
Private Function GetColumnIndex(ColumnName As String, Worksheet As Citishare
WorksheetConfiguration) As Integer
Dim intCounter As Integer = 0
For Each objColumn As CitishareWorksheetConfiguration.CitishareWorksheet
Column In Worksheet.Columns
If objColumn.ExportColumnName.ToUpper() = ColumnName.ToUpper() Then
Return objColumn.ColumnIndex
End If
Next
Return -1
End Function
Private Function GetWorksheetIndex(WorksheetName As String) As Integer
Dim intCounter As Integer = 0
For Each objSheet As CitishareWorksheetConfiguration In arWorksheets
If objSheet.WorksheetName.ToUpper() = WorksheetName.ToUpper() Then

Return intCounter
End If
intCounter += 1
Next
Return -1
End Function
Private Sub FillCollection(colCollection As Collection, strCommand As String
, CMD As SqlCommand)
Dim dtTemp As New DataTable
Dim sda As New SqlDataAdapter(CMD)
sda.SelectCommand.CommandType = CommandType.Text
sda.SelectCommand.CommandText = strCommand
sda.SelectCommand.Parameters.Clear()
sda.Fill(dtTemp)
For Each drRow As DataRow In dtTemp.Rows
colCollection.Add(drRow(0), drRow(0))
Next
sda.Dispose()
dtTemp.Dispose()
End Sub
Public Function GetValue(CurrentRow As WorksheetRow, CurrentColumn As Ci
tishareWorksheetConfiguration.CitishareWorksheetColumn, CurrentWorksheet As Citi
shareWorksheetConfiguration) As Object
Select Case CurrentColumn.ColumnDataType.ToUpper()
Case "TIME"
'TODO: Return a timespan object
Dim tmpTime As String = CurrentRow.Cells(Current
Column.ColumnIndex).Value
If IsNothing(tmpTime) Then
Return DBNull.Value
Else
'Determine if we can parse a date from t
his...
Dim dtTempDate As DateTime = Nothing
If DateTime.TryParse(tmpTime, dtTempDate
) = True Then
Return dtTempDate.TimeOfDay
End If
'It is possible we have an excel date as
well. If we make it here. try and parse excel date
Try
dtTempDate = Date.FromOADate(Cur
rentRow.Cells(CurrentColumn.ColumnIndex).Value)
Return dtTempDate.TimeOfDay
Catch ex As Exception
Me.AddException(New ImportExcept
ion("Could not parse a proper date/time from the value [" & CurrentRow.Cells(Cur
rentColumn.ColumnIndex).Value & "]", CurrentWorksheet, CurrentColumn, CurrentRow
.Index))
Return DBNull.Value
End Try
End If
'Return IIf(IsNothing(CurrentRow.Cells(CurrentCo
lumn.ColumnIndex).Value), DBNull.Value, .TimeOfDay.ToString())

Case "DATE"
If IsNothing(CurrentRow.Cells(CurrentColumn.Colu
mnIndex).Value) Then
Return DBNull.Value
End If
'We need to make sure we get a proper date value
. Excel may store the date as a serial/numeric format...
If IsDate(CurrentRow.Cells(CurrentColumn.ColumnI
ndex).Value) Then
Return Date.Parse(CurrentRow.Cells(Curre
ntColumn.ColumnIndex).Value)
Else
If IsDate(Date.FromOADate(CurrentRow.Cel
ls(CurrentColumn.ColumnIndex).Value)) Then
'We double check that the date p
assed from Excel is not a serial date. If it is, FromOADate should return a vali
d date.
Return Date.FromOADate(CurrentRo
w.Cells(CurrentColumn.ColumnIndex).Value)
End If
End If
Case "BOOLEAN"
'We handle bools in the TrueOrFalse function. An
ything "invalid" is treated as false
If IsNothing(CurrentRow.Cells(CurrentColumn.Colu
mnIndex).Value) Then
Return False
Else
Return TrueOrFalse(CurrentRow.Cells(Curr
entColumn.ColumnIndex).Value)
End If
Case Else
If IsNothing(CurrentRow.Cells(CurrentColumn.Colu
mnIndex).Value) Then
Return DBNull.Value
Else
Return CurrentRow.Cells(CurrentColumn.Co
lumnIndex).Value.ToString()
End If
End Select
'SHOULD NEVER GET HERE!
Return ""
End Function
Public Function ValidateWorkbookSchema(objExcelWorkbook As Workbook) As Bool
ean
Dim bSchemaValid = True
'Now that we have all the worksheets in an array, make sure all the actu
al worksheets and columns required exist in the template provided.
For Each objWorksheet As CitishareWorksheetConfiguration In arWorksheets
Try
If WorksheetExists(objWorksheet.WorksheetName, objExcelWorkbook)
= False Then
'We are missing a worksheet
Throw New ImportException("Worksheet [" & objWorksheet.Works
heetName & "] is missing.", objWorksheet)
Else
Dim tmpUploadedWorksheet As Worksheet = objExcelWorkbook.Wor
ksheets(objWorksheet.WorksheetName)

'Loop through all columns expected and log any errors.


'We store a reference to the actual worksheet in our array
objWorksheet.WorksheetObject = tmpUploadedWorksheet
Dim intColumnCounter As Integer = 0
For Each colRequiredColumn As CitishareWorksheetConfiguratio
n.CitishareWorksheetColumn In objWorksheet.Columns
'WE EXPECT THE COLUMNS TO BE IN THE SAME ORDER AS THEY W
ERE EXPORTED! WE ARE NOT REMAPPING COLUMNS....
If colRequiredColumn.ExportColumn Then
'Only worry about columns that are to be exported
Dim strColumnNameValue As String = ""
If Not IsNothing(tmpUploadedWorksheet.Rows(0).Cells(
intColumnCounter).Formula) And tmpUploadedWorksheet.Rows(0).Cells(intColumnCount
er).HasComment Then
strColumnNameValue = tmpUploadedWorksheet.Rows(0
).Cells(intColumnCounter).Comment.Text.UnformattedString()
ElseIf Not IsNothing(tmpUploadedWorksheet.Rows(0).Ce
lls(intColumnCounter).Value) Then
strColumnNameValue = tmpUploadedWorksheet.Rows(0
).Cells(intColumnCounter).Value.ToString().ToUpper()
Else
strColumnNameValue = ""
End If
If colRequiredColumn.ExportColumnName.ToUpper() <> s
trColumnNameValue.ToUpper() Then
'No sense checking other columns as if one is mi
ssing, the rest will be off anyway.
Throw New ImportException("Worksheet [" & objWor
ksheet.WorksheetName & "] does not have column [" & colRequiredColumn.ExportColu
mnName & "] in expected column [" & intColumnCounter & "]", objWorksheet, colReq
uiredColumn)
End If
intColumnCounter += 1
End If
Next
End If
Catch exImportException As ImportException
Me.AddException(exImportException)
bSchemaValid = False
Catch ex As Exception
'TODO: On a regular exception do we kill this process?
MsgBox("Unhandled Exception! " & ex.Message)
bSchemaValid = False
End Try
Next
Return bSchemaValid
End Function
Public Function ValidateData(objExcelWorkbook As Workbook) As Boolean
Dim bValid As Boolean = True
'We will go through all the Editable worksheets in the workbook and make
sure the data contained in each is valid data type
For Each objWorksheet As CitishareWorksheetConfiguration In arWorksheets
If objWorksheet.WorksheetEditable Then
For intRowCounter As Integer = 1 To objWorksheet
.WorksheetObject.Rows.Count()

'We start after the first row since we a


ssume there is a heading.
'The first blank cell we find in the fir
st column will mark the end of the file...
If IsNothing(objWorksheet.WorksheetObjec
t.Rows(intRowCounter).Cells(0).Value) OrElse Trim(objWorksheet.WorksheetObject.R
ows(intRowCounter).Cells(0).Value.ToString()) = "" Then
Exit For
End If
For Each objColumn As CitishareWorksheet
Configuration.CitishareWorksheetColumn In objWorksheet.Columns
If objColumn.ExportColumn And ob
jColumn.ColumnIndex > -1 Then
Dim tmpCurrentCell As Wo
rksheetCell = objWorksheet.WorksheetObject.Rows(intRowCounter).Cells(objColumn.C
olumnIndex)
If objColumn.ColumnIsRea
donly = ExcelDefaultableBoolean.False Then
'Determine if da
ta is required in this column... IF yes, make sure its not blank.
If objColumn.Dat
aRequiredInColumn And (IsNothing(tmpCurrentCell.Value) OrElse tmpCurrentCell.Val
ue.ToString() = "") Then
Me.AddEx
ception(New ImportException("Column [" & objColumn.ExportColumnName & "] is requ
ried, and no value was supplied for row [" & intRowCounter + 1 & "].", objWorksh
eet, objColumn, intRowCounter + 1))
bValid =
False
End If
'If data is supp
lied, we need to check its validity
If IsNothing(tmp
CurrentCell.Value) = False Then
If Datat
ypeIsValid(objColumn.ColumnDataType, tmpCurrentCell.Value) = False Then
Me.AddException(New ImportException("Column [" & objColumn.ExportColumnName & "]
expecting a [" & objColumn.ColumnDataType & "] datatype, which was not supplied
for row [" & intRowCounter + 1 & "].", objWorksheet, objColumn, intRowCounter +
1))
bValid = False
End If
'Now we
need to add in the business rules required for the data.
If Value
IsValid(tmpCurrentCell.Value, objColumn) = False Then
Me.AddException(New ImportException("Column [" & objColumn.ExportColumnName & "]
contains an invalid value for row [" & intRowCounter + 1 & "].", objWorksheet,
objColumn, intRowCounter + 1))
bValid = False
End If
End If

End If
End If
Next
Next
End If
Next
Return bValid
End Function
Private Function ValueIsValid(strValue As String, objColumn As CitishareWork
sheetConfiguration.CitishareWorksheetColumn) As Boolean
Select Case objColumn.ExportColumnName.ToUpper()
Case "ACCESSIBILITY_ID", "ACCESSIBILITY ID", "SURCHARGE FREE FOR"
Return colBranchAccessibility.Contains(strValue)
Case "REGION ID"
Return colRegions.Contains(strValue)
Case "SERVICE ID", "BRANCH SERVICE ID"
Return colBranchServices.Contains(strValue)
Case "LANGUAGE ID"
Return colLanguages.Contains(strValue)
Case "HOUR TYPE"
Return colHourTypes.Contains(strValue)
Case "TITLE ID"
Return colTitles.Contains(strValue)
Case "SERVICE 1 ID", "SERVICE 2 ID", "SERVICE 3 ID"
Return colTerminalVendorServices.Contains(strValue)
Case "TERMINAL SERVICE ID"
Return colTerminalServices.Contains(strValue)
Case "LOCATION ID"
Return colBranchIDs.Contains(strValue)
Case "TERMINAL ID"
Return colTerminalIDs.Contains(strValue)
Case "LOCATION TYPE ID"
Return colLocationTypes.Contains(strValue)
Case "FACILITY TYPE ID"
Return colFacilityTypes.Contains(strValue)
Case "BRANDING CONFIG ID"
Return colBrandingConfigs.Contains(strValue)
Case "OWNER ID"
Return colOwners.Contains(strValue)
Case "PHONE", "FAX", "INVESTMENT PHONE", "BRANCH OPEN PH
ONE", "BRANCH CLOSE PHONE", "EMERGENCY PHONE"
'Make sure that the phone is valid...
If strValue.Trim(" ").Length = 0 Then
Return True
Else
Return Text.RegularExpressions.Regex.IsMatch(strValue, "^[\d
]{10,15}$")
End If
Case "AIRPORT CODE"
Return Text.RegularExpressions.Regex.IsMatch(str
Value, "^[a-zA-Z]{3}$")
Case Else
Return True
End Select
End Function
Private Function DatatypeIsValid(strDataType As String, strDataToCheck As St

ring) As Boolean
Dim bReturn As Boolean = True
Select Case strDataType.ToUpper()
Case "STRING"
bReturn = True
Case "INTEGER"
If Not IsNumeric(strDataToCheck) Then
bReturn = False
End If
Case "DATE"
If Not IsDate(strDataToCheck) Then
If Not IsDate(Date.FromOADate(strDataToCheck)) Then
'We double check that the date passed from Excel is not
a serial date. If it is, FromOADate should return a valid date.
bReturn = False
End If
End If
Case "TIME"
'TODO: make sure value is actually a time
bReturn = True
Case "BOOLEAN"
'We handle bools in the TrueOrFalse function. Anything "invalid"
is treated as false
bReturn = True
Case Else
'Do we care???
bReturn = True
End Select
Return bReturn
End Function
Public Function LoadData(CMD As SqlCommand, GroupID As Integer, UploadID As
Integer, UserID As Integer) As Boolean
'Load all the data into the database
'At this point we will start a new transaction, if we encounter any erro
rs, we will rollback, otherwise once we make it through we will commit the data.
Dim trnsLoad As SqlTransaction = CMD.Connection.BeginTransaction(System.
Data.IsolationLevel.Snapshot)
CMD.Transaction = trnsLoad
Try
If CMD.Connection.State <> ConnectionState.Open Then
CMD.Connection.Open()
End If
'First wipe all the information in the database for the group ID pas
sed.
'Depending on the groups configuration, this may be wiped from Stagi
ng or Production
CMD.CommandType = CommandType.StoredProcedure
CMD.CommandText = "mgmt.ClearGroupInformationForUpload"
CMD.Parameters.Clear()
CMD.Parameters.AddWithValue("GroupID", GroupID)
CMD.Parameters.AddWithValue("UploadID", UploadID)
CMD.ExecuteNonQuery()
Dim intRowCounter As Integer = 1
For Each objWorksheet As CitishareWorksheetConfiguration In arWorksh

eets
If objWorksheet.WorksheetUploadCommand.ToString() <> "" Then
intRowCounter = 1
CMD.CommandType = CommandType.StoredProcedure
CMD.CommandText = objWorksheet.WorksheetUploadCommand
For Each objRow As WorksheetRow In objWorksheet.WorksheetObj
ect.Rows
'Loop through ALL branches and get all the values we nee
d to add to the SP
'Clear the parameters
CMD.Parameters.Clear()
If intRowCounter > 1 Then
'We skip the first row for headings..
If Not IsNothing(objRow.Cells(0).Value) AndAlso objR
ow.Cells(0).Value.ToString() <> "" Then
If objWorksheet.UploadRequiresRevisionID Then
CMD.Parameters.AddWithValue("RevisionID", DB
Null.Value) 'WE PASS NULL TO INDICATE THAT THE STORED PROC SHOULD LOOKUP THE REV
ISION ID
End If
If objWorksheet.UploadRequiresUserID Then
CMD.Parameters.AddWithValue("UserID", UserID
)
End If
For Each objColumn As CitishareWorksheetConfigur
ation.CitishareWorksheetColumn In objWorksheet.Columns
If objColumn.UploadParameterName <> "" Then
'Add the parameters
CMD.Parameters.AddWithValue(objColumn.UploadParameterName, GetValue(objRow, objC
olumn, objWorksheet))
End If
Next
CMD.ExecuteNonQuery()
Else
Exit For
End If
End If
intRowCounter += 1
Next
End If
Next
'Now we want to merge back in our backed up geocoding in
formation
CMD.CommandType = CommandType.StoredProcedure
CMD.CommandText = "mgmt.MergeGeocodeInformation"
CMD.Parameters.Clear()
CMD.Parameters.AddWithValue("GroupID", GroupID)
CMD.Parameters.AddWithValue("UploadID", UploadID)
CMD.ExecuteNonQuery()
'If we make it this far, commit the transaction
CMD.Transaction.Commit()
Catch ex As Exception
My.Application.Log.WriteException(ex, TraceEventType.Error, "An erro

r occurred when loading data for Group ID: [" & GroupID & "]" & vbCrLf & ex.Stac
kTrace)
Try
CMD.Transaction.Rollback()
Catch exRollback As Exception
My.Application.Log.WriteException(exRollback, TraceEventType.Err
or, "An error occurred when rolling back the transaction! Manual intervention ma
y be needed! Group ID: [" & GroupID & "]" & vbCrLf & exRollback.StackTrace)
End Try
Return False
Finally
CMD.Dispose()
End Try
Return True
End Function
''' <summary>
''' We will treat 'T', 'Y', 'TRUE' as true. Anything else is false
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Private Function TrueOrFalse(strValue As String) As Boolean
If Trim(strValue).ToUpper() = "T" Or Trim(strValue).ToUpper() = "TRUE" O
r Trim(strValue).ToUpper() = "Y" Then
Return True
Else
Return False
End If
End Function
Private Sub AddException(objException As Exception)
Array.Resize(arImportErrors, arImportErrors.Length + 1)
arImportErrors(arImportErrors.Length - 1) = objException
End Sub
Public Function WorksheetExists(WorksheetName As String, Workbook As Workboo
k) As Boolean
For Each Worksheet In Workbook.Worksheets
If Worksheet.Name.ToUpper() = WorksheetName.ToUpper() Then
Return True
End If
Next
Return False
End Function
Public Class CitishareWorksheetConfiguration
Dim _CurrentWorksheetName As String = ""
Dim _colColumns As New Collection
Dim _intNumberOfFrozenColumns As Integer = 0
Dim _bWorksheetEditable As Boolean = False
Dim _objWorksheet As Worksheet = Nothing
Dim _strWorksheetUploadCommand As String = ""
Dim _bUploadRequiresUserID As Boolean = True
Dim _bUploadRequiresRevisionID As Boolean = True
Public Class CitishareWorksheetColumn

Dim _DatasourceColumnName As String = ""


Dim _ExportColumnName As String = ""
Dim _ColumnReadonly As ExcelDefaultableBoolean = ExcelDefaultableBoo
lean.False
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim

_ExportColumn As Boolean = True


_strHyperlinkAddress As String = ""
_intColumnWidth As Integer = 500
_strColumnFormat As String = ""
_strColumnDataType As String = "String"
_intColumnIndex As Integer = 0
_bColumnHidden As Boolean = False
_bDataRequired As Boolean = False
_strUploadParameterName As String = ""

Public Property ExportColumn As Boolean


Get
Return _ExportColumn
End Get
Set(ByVal value As Boolean)
_ExportColumn = value
End Set
End Property
Public Property DatasourceColumnName As String
Get
Return _DatasourceColumnName
End Get
Set(ByVal value As String)
_DatasourceColumnName = value
End Set
End Property
Public Property ExportColumnName As String
Get
Return _ExportColumnName
End Get
Set(ByVal value As String)
_ExportColumnName = value
End Set
End Property
Public Property ColumnIsReadonly As ExcelDefaultableBoolean
Get
Return _ColumnReadonly
End Get
Set(ByVal value As ExcelDefaultableBoolean)
_ColumnReadonly = value
End Set
End Property
Public Property ColumnFormat As String
Get
Return _strColumnFormat
End Get
Set(ByVal value As String)
_strColumnFormat = value
End Set
End Property
Public ReadOnly Property ColumnDataType As String

Get
Return _strColumnDataType
End Get
End Property
Public Property HyperlinkAddress As String
Get
Return _strHyperlinkAddress
End Get
Set(value As String)
'=HYPERLINK("#" &CELL("address", 'Sheet3'!R1),"Test")
_strHyperlinkAddress = value
End Set
End Property
Public Property ColumnWidth As Integer
Get
Return _intColumnWidth
End Get
Set(value As Integer)
_intColumnWidth = value
End Set
End Property
Public ReadOnly Property ColumnIndex As Integer
Get
Return _intColumnIndex
End Get
End Property
Public ReadOnly Property ColumnHidden As Boolean
Get
Return _bColumnHidden
End Get
End Property
Public ReadOnly Property DataRequiredInColumn As Boolean
Get
Return _bDataRequired
End Get
End Property
Public ReadOnly Property UploadParameterName As String
Get
Return _strUploadParameterName
End Get
End Property
Public Sub New(ColumnIndex As Integer, ColumnDataType As String, Dat
aRequired As Boolean, ByVal DatasourceColumnName As String, ByVal ExportColumnNa
me As String, ByVal ColumnIsReadonly As ExcelDefaultableBoolean, ColumnWidth As
Integer, Optional HyperlinkAddress As String = "", Optional ByVal ExportColumn A
s Boolean = True, Optional ColumnFormat As String = "", Optional UploadParameter
Name As String = "")
_intColumnIndex = ColumnIndex
_DatasourceColumnName = DatasourceColumnName
_ExportColumnName = ExportColumnName
_ColumnReadonly = ColumnIsReadonly
_ExportColumn = ExportColumn

_intColumnWidth = ColumnWidth
_strHyperlinkAddress = HyperlinkAddress
_strColumnFormat = ColumnFormat
_strColumnDataType = ColumnDataType
_bDataRequired = DataRequired
_strUploadParameterName = UploadParameterName
End Sub
End Class
Public Property WorksheetObject As Worksheet
Get
Return _objWorksheet
End Get
Set(value As Worksheet)
_objWorksheet = value
End Set
End Property
Public ReadOnly Property NumberOfFrozenColumns As Integer
Get
Return _intNumberOfFrozenColumns
End Get
End Property
Public ReadOnly Property WorksheetName As String
Get
Return _CurrentWorksheetName
End Get
End Property
Public ReadOnly Property Columns As Collection
Get
Return _colColumns
End Get
End Property
Public ReadOnly Property WorksheetEditable As Boolean
Get
Return _bWorksheetEditable
End Get
End Property
Public ReadOnly Property UploadRequiresUserID As Boolean
Get
Return _bUploadRequiresUserID
End Get
End Property
Public ReadOnly Property UploadRequiresRevisionID As Boolean
Get
Return _bUploadRequiresRevisionID
End Get
End Property
Public ReadOnly Property WorksheetUploadCommand As String
Get
Return _strWorksheetUploadCommand
End Get
End Property
Public Sub New(ByVal strWorksheetName As String, ByVal CN As SqlConnecti
on)

_CurrentWorksheetName = strWorksheetName
Dim sda As New SqlDataAdapter("", CN)
Dim dtColumnDefinitions As New DataTable
sda.SelectCommand.CommandType = CommandType.StoredProcedure
sda.SelectCommand.CommandText = "mgmt.GetWorksheetConfiguration"
sda.SelectCommand.Parameters.Clear()
sda.SelectCommand.Parameters.AddWithValue("WorksheetName", strWorksh
eetName)
Dim parNumberOfFrozenColumns As New SqlParameter("NumberOfFrozenColu
mns", 0)
parNumberOfFrozenColumns.Size = 10
parNumberOfFrozenColumns.Direction = ParameterDirection.Output
sda.SelectCommand.Parameters.Add(parNumberOfFrozenColumns)
Dim parEditable As New SqlParameter("WorksheetEditable", False)
parEditable.Size = 10
parEditable.Direction = ParameterDirection.Output
sda.SelectCommand.Parameters.Add(parEditable)
Dim parWorksheetUploadCommand As New SqlParameter("WorksheetUploadCo
mmand", "")
parWorksheetUploadCommand.Size = 200
parWorksheetUploadCommand.Direction = ParameterDirection.Output
sda.SelectCommand.Parameters.Add(parWorksheetUploadCommand)
Dim parUploadRequiresUserID As New SqlParameter("UploadRequiresUserI
D", False)
parUploadRequiresUserID.Size = 10
parUploadRequiresUserID.Direction = ParameterDirection.Output
sda.SelectCommand.Parameters.Add(parUploadRequiresUserID)
Dim parUploadRequiresRevisionID As New SqlParameter("UploadRequiresR
evisionID", False)
parUploadRequiresRevisionID.Size = 10
parUploadRequiresRevisionID.Direction = ParameterDirection.Output
sda.SelectCommand.Parameters.Add(parUploadRequiresRevisionID)
sda.Fill(dtColumnDefinitions)
_intNumberOfFrozenColumns = parNumberOfFrozenColumns.Value
_bWorksheetEditable = CBool(parEditable.Value)
_strWorksheetUploadCommand = parWorksheetUploadCommand.Value.ToStrin
g()
_bUploadRequiresUserID = parUploadRequiresUserID.Value
_bUploadRequiresRevisionID = parUploadRequiresRevisionID.Value
Dim intExportedColumnIndex As Integer = 0
Dim intTmpColumnIndex As Integer = -1
For Each drColumn As DataRow In dtColumnDefinitions.Rows
If CBool(drColumn("output_to_excel")) = True Then
intTmpColumnIndex = intExportedColumnIndex
intExportedColumnIndex += 1
Else
intTmpColumnIndex = -1
End If
Me.Columns.Add(New CitishareWorksheetColumn(intTmpColumnIndex, d
rColumn("column_datatype"), drColumn("data_required"), drColumn("datasource_colu
mnname"), drColumn("export_columnname"), IIf(CBool(drColumn("allow_excel_edit"))

, ExcelDefaultableBoolean.False, ExcelDefaultableBoolean.True), drColumn("column


_width"), drColumn("hyperlink_address").ToString(), drColumn("output_to_excel"),
drColumn("column_format").ToString(), drColumn("upload_parameter_name").ToStrin
g()), drColumn("datasource_columnname"))
Next
dtColumnDefinitions.Dispose()
sda.Dispose()
End Sub
End Class
Public Class ImportException
Inherits System.Exception
Dim _strErrorDescription As String
Dim _objWorksheetCausingIssue As CitishareWorksheetConfiguration
Dim _objColumnCausingIssue As CitishareWorksheetConfiguration.CitishareW
orksheetColumn
Dim _intRowNumber As Integer = -1
Public ReadOnly Property RowNumber As Integer
Get
Return _intRowNumber
End Get
End Property
Public ReadOnly Property ErrorMessage As String
Get
Return _strErrorDescription
End Get
End Property
Public ReadOnly Property Worksheet As CitishareWorksheetConfiguration
Get
Return _objWorksheetCausingIssue
End Get
End Property
Public ReadOnly Property WorksheetColumn As CitishareWorksheetConfigurat
ion.CitishareWorksheetColumn
Get
Return _objColumnCausingIssue
End Get
End Property
Public Sub New(ErrorDescription As String, Optional Worksheet As Citisha
reWorksheetConfiguration = Nothing, Optional WorksheetColumn As CitishareWorkshe
etConfiguration.CitishareWorksheetColumn = Nothing, Optional RowNumber As Intege
r = -1)
_strErrorDescription = ErrorDescription
_objColumnCausingIssue = WorksheetColumn
_objWorksheetCausingIssue = Worksheet
_intRowNumber = RowNumber
End Sub
End Class
End Class