Hi all I'm using Open XML and ExtremML to generate an Excel File on the Server and Download it, but when you I try to open it it gives me the error "EXCEL FOUND UNREADABLE CONTENT. DO YOU WANT TO RECOVER THE CONTENTS OF THIS WORKBOOK?
IF YOU TRUST THE SOURCE OF THIS WORKBOOK, CLICK YES", so checking on the file inside y found it's adding a tag named company, that when i remove it it corrects the error that Excel is giving, It's in VB .NET, this is my code:
Protected Sub btnExcel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExcel.Click
Dim iProcess As String = ""
Dim loOraClientDb As clsOraClientDb = New clsOraClientDb
Dim vFilename As String = ""
Try
Try
iProcess = "btnExcel_Click 1"
Dim ExcelSendInfo As DataTable = Session("dtExcel")
Dim ExcelExportedInfo As DataTable = New DataTable
Dim PkgOutValues() As String = {}
Dim ExcelDataSet As DataSet = New DataSet
Dim vtablename As String = ""
Dim vtabletoname As String = ""
Dim WFT As New WebFileTools
If chkFLayout.Checked Then
iProcess = "btnExcel_Click 2"
Dim sDNS As StringBuilder = New StringBuilder()
If Not chkFInfo.Checked Then
For Each dr In ExcelSendInfo.Rows
sDNS.AppendLine(dr(0))
Next
End If
iProcess = "btnExcel_Click 3"
If Not loOraClientDb.Open(ConnectionStrings("DatabaseSDSTP6301").ConnectionString) Then
EnableErrorByState(loOraClientDb.Message & ", Process: " & iProcess)
Exit Sub
Else
iProcess = "btnExcel_Click 4"
Dim vStatus As String
If ViewState("CurrentWindow") = "Report" Then
vStatus = "G.G_STATUSID!=2"
Else
vStatus = "G.G_STATUSID=2"
End If
iProcess = "btnExcel_Click 5"
Dim PkgInParameters(6)() As String
PkgInParameters(0) = New String() {"VEXPORTEDDNS", "VARCHAR2", "Empty", sDNS.ToString.Replace(Chr(13) & Chr(10), ",")}
PkgInParameters(1) = New String() {"VSTATUS", "VARCHAR2", "Empty", vStatus}
PkgInParameters(2) = New String() {"chkFInfo", "VARCHAR2", "Empty", BoolToStr(chkFInfo.Checked)}
PkgInParameters(3) = New String() {"VSEARCHOPS", "VARCHAR2", "Empty", DDLSearchOps.SelectedValue}
PkgInParameters(4) = New String() {"VSEARCH", "VARCHAR2", "Empty", txtsearch.Text}
PkgInParameters(5) = New String() {"VRANGE1", "VARCHAR2", "Empty", txtrange1.Text}
PkgInParameters(6) = New String() {"VRANGE2", "VARCHAR2", "Empty", txtrange2.Text}
Dim PkgReturnParameters() As String
PkgReturnParameters = New String() {"VRETURN", "CURSOR", "Empty"}
Dim PkgOutParameters(0)() As String
PkgOutParameters(0) = New String() {"VTOTPROJS", "NUMBER", "Empty"}
iProcess = "btnExcel_Click 6"
If Not loOraClientDb.ExecuteProcedureFunction("PKG_GENERALINFO.GENERATEEXCEL", PkgInParameters, _
PkgOutParameters, PkgReturnParameters, , ExcelExportedInfo, _
, PkgOutValues) Then
EnableErrorByState(loOraClientDb.Message & ", Process: " & iProcess)
Exit Sub
End If
vtablename = "MAININFO"
vtabletoname = "MAINTABLE"
End If
Else
iProcess = "btnExcel_Click 7"
ExcelExportedInfo = ExcelSendInfo
vtablename = "TIMEREP"
vtabletoname = "TIMEREPORT"
End If
ExcelDataSet.Tables.Add(ExcelExportedInfo)
ExcelDataSet.Tables(0).TableName = vtablename
Dim vFileTemplate As String = ""
Dim RandomNumber As New Random()
If vtablename = "MAININFO" Then
vFileTemplate = "FullLayout.xlsx"
vFilename = "FullLayout" & RandomNumber.Next(1000).ToString & ".xlsx"
Else
vFileTemplate = "TimeReport.xlsx"
vFilename = "TimeReport" & RandomNumber.Next(1000).ToString & ".xlsx"
End If
Session("vfilename") = vFilename
WFT.CopyServerFile("ExcelTemplates\" & vFileTemplate, "ExcelTemplates\" & vFilename, True)
Using DPSExcelTemplate = ExcelOpenPackage(Server.MapPath(".") & "\ExcelTemplates", vFilename.Replace(".xlsx", ""))
ExcelWorkBookPopulateDS2Table(DPSExcelTemplate, ExcelDataSet, vtablename, vtabletoname)
End Using
Server.ClearError()
Response.Redirect("DownloadPage.aspx", False)
iProcess = "btnExcel_Click 28"
Catch ex As Exception
EnableErrorByState(ex.Message & ", Process: " & iProcess)
If File.Exists(Server.MapPath(".") & "\ExcelTemplates\" & vFilename) = True Then
File.Delete(Server.MapPath(".") & "\ExcelTemplates\" & vFilename)
End If
End Try
Finally
loOraClientDb.Close()
ShowCorrespondingWindows()
End Try
End Sub
The page DownloadPage.aspx has this code:
Imports WebFileTools
Imports System.IO
Partial Class DownloadPage
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim vfilename = Session("vfilename").ToString
Dim nfilename = ""
If vfilename.IndexOf("FullLayout") <> -1 Then
nfilename = "FullLayout_" & Today.ToShortDateString
Else
nfilename = "TimeReport_" & Today.ToShortDateString
End If
Dim WFT As New WebFileTools
WFT.DownloadServerFile("ExcelTemplates\" & vfilename, MIMEType.Excel2007, nfilename)
End Sub
End Class
I can't seem to find the problem has anyone gotten this error or knows how to fix this problem?
I Forgot to add this code thats for generating the Excel file with ExtremMl:
Public Shared Function ExcelOpenPackage(ByVal ServerPath As String, _
ByVal ExcelFileName As String) As ExtremeML.Packaging.SpreadsheetDocumentWrapper
Dim ExcelPackage = SpreadsheetDocumentWrapper.Open(ServerPath & "\" & ExcelFileName & ".xlsx")
Return ExcelPackage
End Function
And this is to fill the info on the file:
Public Shared Sub ExcelWorkBookPopulateDS2Table(ByRef ExcelPackage As ExtremeML.Packaging.SpreadsheetDocumentWrapper, _
ByRef Data As DataSet, _
ByVal DataTableName As String, _
ByVal ExcelTableName As String)
Dim ExcelTable = ExcelPackage.WorkbookPart.GetTablePart(ExcelTableName).Table
ExcelTable.Fill(Data, DataTableName)
End Sub
I don't know exactly why but the problem was with my Download code previusly it was like this:
Public Sub DownloadServerFile(ByVal FileToDownload As String, ByVal MIMETYPE As MIMEType, Optional ByVal NewNameOfFileToDownload As String = "")
Dim FileExt As String = ""
Dim F2DArr As String = Path.GetFileName(FileToDownload)
Current.Response.ClearContent()
Current.Response.ClearHeaders()
Select Case MIMETYPE
Case WebFileTools.MIMEType.Excel2007
Current.Response.ContentType = _
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
FileExt = ".xlsx"
Case WebFileTools.MIMEType.Word2007
Current.Response.ContentType = _
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
FileExt = ".docx"
Case WebFileTools.MIMEType.PowerPoint2007
Current.Response.ContentType = _
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
FileExt = ".pptx"
End Select
If NewNameOfFileToDownload.Trim.Length > 0 Then
Current.Response.AppendHeader("content-disposition", "inline;attachment;filename=" _
& NewNameOfFileToDownload & FileExt)
Else
Current.Response.AppendHeader("content-disposition", "inline;attachment;filename=" & F2DArr)
End If
Current.Response.Clear()
Current.Response.TransmitFile(Server.MapPath(".") & "\" & FileToDownload)
Current.Response.Flush()
If File.Exists(Server.MapPath(".") & "\" & FileToDownload) = True Then
File.Delete(Server.MapPath(".") & "\" & FileToDownload)
End If
Current.ApplicationInstance.CompleteRequest()
End Sub
Now i changed this line Current.ApplicationInstance.CompleteRequest() for Current.Response.End() and the file gets downloaded correclty
and now i cant call my download code directly:
Server.ClearError()
WFT.DownloadServerFile("ExcelTemplates\" & vFilename, MIMEType.Excel2007, nfilename)
iProcess = "btnExcel_Click 28"
Catch ex As Exception
EnableErrorByState(ex.Message & ", Process: " & iProcess)
If File.Exists(Server.MapPath(".") & "\ExcelTemplates\" & vFilename) = True Then
File.Delete(Server.MapPath(".") & "\ExcelTemplates\" & vFilename)
End If
End Try
Finally
loOraClientDb.Close()
ShowCorrespondingWindows()
End Try
It's not suposed to be the correct way of using Response.End, because it always trows an error but I don't now if this is the correct way of using Current.ApplicationInstance.CompleteRequest() or that Response.End does something that CompleteRequest is not doing in order for it to get the correct MIME Type
Related
We have added 5 new columns to three sheets in a workbook. The first sheet is like a staging table that then populates the other two. The problem is the new columns are not being populated with the data in the two final sheets. The data is visible in the intial sheet. I think it may be an issue with the Advanced Filter but im not sure. Any help would be appreciated.
Public Sub RunExtract()
Dim strExtractYear As String
Dim strExtractMonth As String
Dim strOutputFolder As String
Application.ScreenUpdating = False
'grab the control variable values
strExtractYear = Range("Extract_Year").Value
strExtractMonth = Range("Extract_Month").Value
strOutputFolder = Range("Output_Folder").Value
'pull the data
Application.StatusBar = "Pulling data..."
Call PullData(strExtractYear, strExtractMonth)
'filter and output the results
Application.StatusBar = "Extracting 310 summary data..."
Range("SummaryFilter.Criteria").Cells(2, 2).Formula = "=""=310"""
Call FilterData(Range("SalesExtract.Table"), Range("SummaryFilter.Criteria"), Range("SummaryFilter.Header"), "SummaryFilter.Table")
Call OutputResults("SUMMARY", "310", strOutputFolder)
Application.StatusBar = "Extracting 430 summary data..."
Range("SummaryFilter.Criteria").Cells(2, 2).Formula = "=""=430"""
Call FilterData(Range("SalesExtract.Table"), Range("SummaryFilter.Criteria"), Range("SummaryFilter.Header"), "SummaryFilter.Table")
Call OutputResults("SUMMARY", "430", strOutputFolder)
Application.StatusBar = "Extracting 310 detail data..."
Range("DetailFilter.Criteria").Cells(2, 2).Formula = "=""=310"""
Call FilterData(Range("SalesExtract.Table"), Range("DetailFilter.Criteria"), Range("DetailFilter.Header"), "DetailFilter.Table")
Call OutputResults("DETAIL", "310", strOutputFolder)
Application.StatusBar = "Extracting 430 detail data..."
Range("DetailFilter.Criteria").Cells(2, 2).Formula = "=""=430"""
Call FilterData(Range("SalesExtract.Table"), Range("DetailFilter.Criteria"), Range("DetailFilter.Header"), "DetailFilter.Table")
Call OutputResults("DETAIL", "430", strOutputFolder)
Call CleanUpThisWorkbook
Application.StatusBar = "Done"
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Public Sub PullData(ExtractYear As String, ExtractMonth As String)
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim strStartDate As String
Dim strStartDateTime As String
Dim strEndDateTime As String
Dim strYear As String
Dim strMonth As String
Dim strLastDay As String
'clear the existing range
Range("SalesExtract.Table").CurrentRegion.Offset(1).EntireRow.Delete
'figure out the start and end datetimes
strYear = ExtractYear
strMonth = Right("0" & ExtractMonth, 2)
strStartDate = "{year}-{month}-{day}"
strStartDate = Replace(strStartDate, "{year}", strYear)
strStartDate = Replace(strStartDate, "{month}", strMonth)
strStartDate = Replace(strStartDate, "{day}", "01")
strStartDateTime = strStartDate & " 00:00:00"
strLastDay = CStr(Day(DateSerial(Year(strStartDate), Month(strStartDate) + 1, 0)))
strEndDateTime = "{year}-{month}-{day} 23:59:59"
strEndDateTime = Replace(strEndDateTime, "{year}", strYear)
strEndDateTime = Replace(strEndDateTime, "{month}", strMonth)
strEndDateTime = Replace(strEndDateTime, "{day}", strLastDay)
Private Sub OutputResults(Level As String, Company As String, Directory As String)
Dim wb As Workbook
Set wb = Workbooks.Add
Dim strSheet As String
If Level = "SUMMARY" Then
strSheet = "SummaryFilter"
ElseIf Level = "DETAIL" Then
strSheet = "DetailFilter"
Else
'raise error
End If
Call ThisWorkbook.Worksheets(strSheet).Range(strSheet & ".Table").Copy
Call wb.Worksheets(1).Range("A1").PasteSpecial(xlPasteValues)
Call ThisWorkbook.Worksheets(strSheet).Range(strSheet & ".ReplacementHeader").Copy
Call wb.Worksheets(1).Range("A1").PasteSpecial(xlPasteValues)
wb.Worksheets(1).Name = Level & " " & Company
Application.DisplayAlerts = False
Call wb.SaveAs(Directory & "\Sales Extract - " & Level & " " & Company & ".xlsx")
Application.DisplayAlerts = True
Call wb.Close
Set wb = Nothing
End Sub
Private Sub FilterData(FilterRng As Range, CriteriaRng As Range, CopyToRng As Range, NameMe As String, Optional FilterUnique As Boolean)
With CopyToRng
If WorksheetFunction.CountA(.Offset(1, 0).Resize(1, .Columns.Count)) <> 0 Then
CopyToRng.CurrentRegion.Offset(1, 0).ClearContents
End If
End With
FilterRng.AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=CriteriaRng, _
CopyToRange:=CopyToRng, _
Unique:=FilterUnique
CopyToRng.CurrentRegion.Name = NameMe
End Sub
Private Sub CleanUpThisWorkbook()
Range("SalesExtract.Table").Offset(1).EntireRow.Delete
Range("SummaryFilter.Table").Offset(1).EntireRow.Delete
Range("DetailFilter.Table").Offset(1).EntireRow.Delete
End Sub
How do I rename an OLEObject?
The object is embedded and the oname variable works when used in the other lines but the .name command will not work. There is no error.
Public Sub insertFiles()
Dim newObject As Object
Dim oname As String
Dim CheckName As String
CheckName = UserForm1.MultiPage2.SelectedItem.Caption
oname = CheckName & "_" & "Evidence" & "_" & UserForm1.ProjectName.Value & "_" & Format(Date, "ddmmmyyyy")
Worksheets("Emails").Activate
Range("A" & Rows.Count).End(xlUp).Offset(1).Select
Set Rng = ActiveCell
Rng.RowHeight = 70
On Error Resume Next
fpath = Application.GetOpenFilename("All Files,*.*", Title:="Select file")
If LCase(fpath) = "false" Then Exit Sub
If UserForm1.ProjectName.Value <> Empty Then
ActiveCell.Value = "."
ActiveSheet.OLEObjects.Add(Filename:=fpath, _
Link:=False, _
DisplayAsIcon:=True, _
IconFileName:="Outlook.msg", _
IconIndex:=1, _
IconLabel:=extractFileName(fpath)).Name = oname
ActiveCell.Offset(0, 1).Value = oname
UserForm1.Attached1.Value = oname
ThisWorkbook.Worksheets("Output").Range("B35").Value = oname
Call UserForm1.Tickbox
UserForm1.LablePIA.Visible = True
UserForm1.Attached1.Visible = True
UserForm1.View.Visible = True
UserForm1.Deleteemail.Visible = True
MsgBox "Attachment uploaded"
Else
MsgBox "Project Name must be input before emails can be uploaded"
End If
End Sub
Public Function extractFileName(filePath)
For i = Len(filePath) To 1 Step -1
If Mid(filePath, i, 1) = "\" Then
extractFileName = Mid(filePath, i + 1, Len(filePath) - i + 1)
Exit Function
End If
Next
End Function
Solution:
The string variable contained too many characters, apparently the max is 35.
OLEObject names cannot exceed 35 characters (presumably unless you use a class module etc!).
Try like this
Dim Obj As OLEObject
set Obj = ActiveSheet.OLEObjects.Add(Filename:=fpath, _
Link:=False, _
DisplayAsIcon:=True, _
IconFileName:="Outlook.msg", _
IconIndex:=1, _
IconLabel:=extractFileName(fpath))
Obj.name = oname
I have already run these codes successfully more than 200 times as I download files on daily basis.
Also having another copies of same code in different drives as reference in case of any issue.
Last night I re-installed my Win10 and office 2019 pro plus both are updated to latest.
And now the codes are not running.
I am not a hard core programmer, not able to understand what's wrong with them. Do I need to install any reference library or .net framework or something else.
The codes stopped at
"Name oldFullName As newfullname"
2 files are there do be downloaded and renamed
The codes get 1st file successfully but, do not rename it so not going to 2nd loop to download 2nd file and to further rename that.
Public IsExit As Boolean
Global Path As String
Private Sub Download_AllZip()
Path = ThisWorkbook.Worksheets("Downloads").Range("C3").Value
Application.ScreenUpdating = FALSE
Application.EnableEvents = FALSE
Dim LR As Long
Dim Fileurl As String, Filename As String, y As String, z As String 'msg as string
Dim r As Long
LR = Sheets("Downloads").Range("C6").Row
For r = 5 To LR
Fileurl = Sheets("Downloads").Range("C" & r).Value
If InStr(1, Fileurl, ".zip") <> 0 Then
filepath = Path
End If
Dim Obj1 As Object
Set Obj1 = CreateObject("Microsoft.XMLHTTP")
Obj1.Open "GET", Fileurl, FALSE
Obj1.send
If Obj1.Status = 200 Then
Set Obj2 = CreateObject("ADODB.Stream")
Obj2.Open
Obj2.Type = 1
Obj2.Write Obj1.responseBody
Obj2.SaveToFile (filepath & getfilename(Fileurl)), 2 ' 1 = no overwrite, 2 = overwrite
Call UnzipFileRename(filepath & getfilename(Fileurl), filepath, Sheets("Downloads").Range("D" & r).Value)
Obj2.Close
y = (y & vbCr & Sheets("Downloads").Range("D" & r).Value & " = Downloaded & Converted To .CSV in " & filepath)
ThisWorkbook.Sheets("Downloads").Range("E" & r).Value = "Downloaded" '/STATUS
Else
z = (z & vbCr & Sheets("Downloads").Range("D" & r).Value & " = Failed To Download")
ThisWorkbook.Sheets("Downloads").Range("E" & r).Value = "Failed" '/STATUS
End If
Next r
End Sub
Function getfilename(filepath As String)
Dim v_string() As String
v_string = Split(filepath, "/")
getfilename = v_string(UBound(v_string))
End Function
Private Sub UnzipFileRename(zipFullName As Variant, unzipPath As Variant, newName As String)
Dim ShellApp As Object, oldFullName As String, newfullname As String, n As Variant
Set ShellApp = CreateObject("Shell.Application")
'/get file name
For Each n In ShellApp.Namespace(zipFullName).Items
a = a + 1
oldFullName = unzipPath & n.Name
newfullname = unzipPath & newName
If a = 1 Then Exit For
Next n
'/delete previous version to avoid any issues
DeleteFile oldFullName
DeleteFile newfullname
'/unzip the file
ShellApp.Namespace(unzipPath).CopyHere ShellApp.Namespace(zipFullName).Items
'/rename the file
Name oldFullName As newfullname
'/delete zip file
DeleteFile CStr(zipFullName)
End Sub
Private Sub DeleteFile(PathAndName As String)
On Error Resume Next
Kill PathAndName
On Error GoTo 0
End Sub
Im trying my first attempt at getting a recordset from a SQL server and passing the data from the recordset into a class. This is going to be part of a much bigger project by storing the recordsets into a dictionary that I can call on based on a user entered search criteria, which im sure I will get stuck on too. I used the Answer from this question as a guide to get me started, but since Im just now learning about using the Class Module; I am not sure why I am getting the Run-time error 91(identified in the code below). I have noticed that nothing seems to pass to the variables that I have designated within the clsCustInfo. Thank you for your assistance.
On quick side note: The On Error Resume Next is for the error that happens when the function tests to see which server the data is stored on.
Below is what is in my Class Module.
'CustomerInfo.cls
Private CustomerId As String
Private cName As String
Private cAddress1 As String
Private cAddress2 As String
Private cCity As String
Private cState As String
Private cZip As String * 5
Private cDoB As String
Private TableName As String
Private ErrNumber As Long
Public Property Get custID() As String
custID = CustomerId
End Property
Public Property Let custID(value As String)
custID = value
End Property
Public Property Get custName() As String
custName = cName
End Property
Public Property Let custName(value As String)
custName = value
End Property
Public Property Get custAddress1() As String
custAddress1 = cAddress1
End Property
Public Property Let custAddress1(value As String)
custAddress1 = value
End Property
Public Property Get custAddress2() As String
custAddress2 = cAddress2
End Property
Public Property Let custAddress2(value As String)
custAddress2 = value
End Property
Public Property Get custCity() As String
custCity = cCity
End Property
Public Property Let custCity(value As String)
custCity = value
End Property
Public Property Get custState() As String
custState = cState
End Property
Public Property Let custState(value As String)
custState = value
End Property
Public Property Get custZip() As String
custZip = cZip
End Property
Public Property Let custZip(value As String)
custZip = value
End Property
Public Property Get custDoB() As String
custDoB = cDoB
End Property
Public Property Let custDoB(value As String)
custDoB = value
End Property
Public Property Get tName() As String
tName = TableName
End Property
Public Property Let tName(value As String)
tName = value
End Property
Public Property Get eNumber() As Long
eNumber = ErrNumber
End Property
Public Property Let eNumber(value As Long)
eNumber = value
End Property
Below is in a Standard Module:
Option Explicit
Const CONNSTR = REDACTED FOR PUBLIC VIEWING
Const ConnectionError As Long = -2147467259
Sub CIFGrab()
Const bhschlp8 As String = "bhschlp8.jhadat842"
Const cncttp08 As String = "cncttp08.jhadat842"
Application.ScreenUpdating = False
'\\\\DATABASE OPERATIONS////
Dim tDBGrabRecord As clsCustInfo
tDBGrabRecord.tName = getCIFDBGrabTestRecord(cncttp08) <---ERROR 91 Happens on this line
If tDBGrabRecord.eNumber = ConnectionError Then tDBGrabRecord = getCIFDBGrabTestRecord(bhschlp8)
End Sub
Function getCIFDBGrabTestRecord(ByVal tName As String) As clsCustInfo
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim SQL As String
Dim tDBGrabRecord As clsCustInfo
On Error Resume Next
conn.Open CONNSTR
SQL = getCIFDBGrabSQL(tName)
rs.Open SQL, conn
tDBGrabRecord.eNumber = Err.Number
If Not (rs.BOF And rs.EOF) Then
rs.MoveFirst
If Not tDBGrabRecord.eNumber = ConnectionError Then
With tDBGrabRecord
.custID = Trim(rs.Fields("cifNum").value)
.custName = Trim(rs.Fields("custName").value)
.custAddress1 = Trim(rs.Fields("stAdd1").value)
.custAddress2 = Trim(rs.Fields("stAdd2").value)
.custCity = Trim(rs.Fields("City").value)
.custState = Trim(rs.Fields("State").value)
.custZip = Trim(rs.Fields("Zip").value)
.custDoB = Trim(rs.Fields("DoB").value)
.tName = tName
End With
rs.MoveNext
With tDBGrabRecord
Debug.Print "CIF:", .custID, "Name:", .custName, "Street 1:", .custAddress1, _
"Street 2:", .custAddress2, "City:", .custCity, "State:", .custState, _
"Zip:", .custZip, "DoB:", .custDoB
End With
End If
End If
rs.Close
conn.Close
getCIFDBGrabTestRecord = tDBGrabRecord
End Function
Function getCIFDBGrabSQL(ByVal TableName As String) As String
Dim SelectClause As String
Dim FromClause As String
Dim WhereClause As String
Dim JoinClause As String
SelectClause = "SELECT " & _
"cfcif# AS cifNum, cfna1 AS custName, " & _
"cfna2 AS stAdd1, cfna3 AS stAdd2, " & _
"cfcity AS City, cfstat AS State, " & _
"left(cfzip,5) AS Zip, " & _
"date(digits(decimal(cfdob7 + 0.090000, 7, 0))) AS DoB"
FromClause = "FROM " & TableName & ".cfmast cfmast"
WhereClause = "WHERE cfdead = '" & "N" & "'"
getCIFDBGrabSQL = SelectClause & vbNewLine & FromClause & vbNewLine & WhereClause
End Function
Something like this should work - I refactored a little bit.
Compiled but not tested.
Option Explicit
Const CONNSTR = "REDACTED FOR PUBLIC VIEWING"
Sub CIFGrab()
Const bhschlp8 As String = "bhschlp8.jhadat842"
Const cncttp08 As String = "cncttp08.jhadat842"
Dim tDBGrabRecord As clsCustInfo
'passing in all potential table names/sources in array
Set tDBGrabRecord = getCIFDBGrabTestRecord(Array(bhschlp8, cncttp08))
If tDBGrabRecord Is Nothing Then
MsgBox "Failed to get record", vbExclamation
Else
'work with tDBGrabRecord
End If
End Sub
Function getCIFDBGrabTestRecord(arrNames) As clsCustInfo
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim SQL As String, nm, okSql As Boolean
Dim tDBGrabRecord As clsCustInfo
conn.Open CONNSTR
'try each provided name: exit loop on successful query
For Each nm In arrNames
SQL = getCIFDBGrabSQL(CStr(nm))
On Error Resume Next
rs.Open SQL, conn 'try this name
If Err.Number = 0 Then okSql = True
On Error GoTo 0 'cancel on error resume next
If okSql Then
If Not rs.EOF Then
Set tDBGrabRecord = New clsCustInfo 'create an instance to populate
With tDBGrabRecord
.custID = Trim(rs.Fields("cifNum").value)
.custName = Trim(rs.Fields("custName").value)
.custAddress1 = Trim(rs.Fields("stAdd1").value)
.custAddress2 = Trim(rs.Fields("stAdd2").value)
.custCity = Trim(rs.Fields("City").value)
.custState = Trim(rs.Fields("State").value)
.custZip = Trim(rs.Fields("Zip").value)
.custDoB = Trim(rs.Fields("DoB").value)
.tName = CStr(nm)
Debug.Print "CIF:", .custID, "Name:", .custName, "Street 1:", .custAddress1, _
"Street 2:", .custAddress2, "City:", .custCity, "State:", .custState, _
"Zip:", .custZip, "DoB:", .custDoB
End With
'rs.MoveNext 'surely this is not needed here?
End If
Exit For 'done trying names
End If
Next nm
If rs.State = adStateOpen Then rs.Close
If conn.State = adStateOpen Then conn.Close
Set getCIFDBGrabTestRecord = tDBGrabRecord
End Function
Function getCIFDBGrabSQL(ByVal TableName As String) As String
Dim SelectClause As String
Dim FromClause As String
Dim WhereClause As String
Dim JoinClause As String
SelectClause = "SELECT " & _
"cfcif# AS cifNum, cfna1 AS custName, " & _
"cfna2 AS stAdd1, cfna3 AS stAdd2, " & _
"cfcity AS City, cfstat AS State, " & _
"left(cfzip,5) AS Zip, " & _
"date(digits(decimal(cfdob7 + 0.090000, 7, 0))) AS DoB"
FromClause = "FROM " & TableName & ".cfmast cfmast"
WhereClause = "WHERE cfdead = '" & "N" & "'"
getCIFDBGrabSQL = SelectClause & vbNewLine & FromClause & vbNewLine & WhereClause
End Function
I have 2 workbooks: "reportPageImpression.xlsx" and "testCloseWorkbook.xslx". Currently I am able to get data from reportPageImpression to testCloseWorkbook when clicking the "Update" button.
What I try to do is when clicking again the "Update" button, the value will go to "Jan-16" (new column) and so on. Here's my code:
Option Explicit
Private Function GetValueFromClosedWorkbook(path, file, sheet, ref)
Dim arg As String
'Let’s check whether the file exists
If Right(path, 1) <> "\" Then path = path & "\"
If Dir(path & file) = "" Then
GetValueFromClosedWorkbook = "File Not Found"
Exit Function
End If
'We create the argument
arg = "'" & path & "[" & file & "]" & sheet & "'!" & _
Range(ref).Range("A1").Address(, , xlR1C1)
'MsgBox arg
'Now we execute an XLM macro
'All references must be given as R1C1 strings.
GetValueFromClosedWorkbook = ExecuteExcel4Macro(arg)
End Function
Sub TestGetValueFromClosedWorkbook()
Dim p As String, f As String
Dim s As String, a As String
p = ThisWorkbook.path
f = "reportPageImpression.xlsx"
s = "report_page_impression"
a = "D39"
ActiveSheet.Range("C8") = GetValueFromClosedWorkbook(p, f, s, a)
End Sub
ActiveSheet.Cells(Range("C8").Row, Columns.Count).End(xlToLeft).Offset(0, 1) = GetValueFromClosedWorkbook(p, f, s, a)
to check for a cell to be empty you must use a formula like "COUNTA(range)" as the argument of the ExecuteExcel4Macro(arg) method and get back the number of non empty cells in the closed workbook specified range.
If you specify your cell address as its range and it returns zero then that cell is empty otherwise it has a value and then you can use ExecuteExcel4Macro(arg) method again with the cell reference as its argument. In this latter case you may want to use .Offset(rowOffset) method on your original "Range" to shift to a cell rowOffset rows apart from it.
In order not to get lost in references, I'd suggest you to refactor your code and make extensive use of "wrappers" in order to have clean an maintanable code
Here you may find what I've come up to as per my understanding
Sub TestGetValueFromClosedWorkbook()
Dim p As String, f As String
Dim s As String, a As String
Dim argPart As String
Dim var As Variant
Dim checkSheetResult As String
p = ThisWorkbook.path
f = "reportPageImpression.xlsx"
s = "report_page_impression"
a = "D39"
checkSheetResult = CheckSht(p, f) ' check if the file to be read as closed is not already opened and if it exists
If checkSheetResult = "" Then
argPart = "'" & p & "[" & f & "]" & s & "'!" 'set the "constant" part of the argument
var = GetFirstNonEmptyValueFromClosedWorkbook(a, argPart, -1)
If var = -1 Then
MsgBox ("No value found!")
Else
ActiveSheet.Cells(Range("C8").row, Columns.Count).End(xlToLeft).Offset(0, 1) = var
End If
Else
MsgBox checkSheetResult
End If
End Sub
Private Function GetFirstNonEmptyValueFromClosedWorkbook(ref As String, argPart As String, Optional rowOffsetRate As Variant) As Variant
Dim arg As String, funcArg As String
Dim var As Variant
Dim rowOffset As Long
If IsMissing(rowOffsetRate) Then rowOffsetRate = 0
rowOffset = 0
funcArg = SetArgFunction(ref, argPart, rowOffset, arg)
var = ExecuteExcel4Macro(funcArg)
Do While var = -1 And CheckIfOffset(ref, CLng(rowOffsetRate), rowOffset)
funcArg = SetArgFunction(ref, argPart, rowOffset, arg)
var = ExecuteExcel4Macro(funcArg)
Loop
If var <> -1 Then var = ExecuteExcel4Macro(arg)
GetFirstNonEmptyValueFromClosedWorkbook = var
End Function
Private Function SetArgFunction(ref As String, argPart As String, rowOffset As Long, arg As String) As String
arg = argPart & Range(ref).Range("A1").Offset(rowOffset).Address(, , xlR1C1)
SetArgFunction = "IF(COUNTA(" & arg & ")>0,1,-1)"
End Function
Private Function CheckIfOffset(ref As String, rowOffsetRate As Long, rowOffset As Long) As Boolean
Dim nextRow As Long
Dim cell As Range
Set cell = Range(ref)
nextRow = cell.Offset(rowOffset).row + rowOffsetRate
CheckIfOffset = rowOffsetRate > 0 And nextRow <= cell.Parent.Cells(cell.Parent.Rows.Count, 1).row _
Or (rowOffsetRate < 0 And nextRow > 0)
If CheckIfOffset Then rowOffset = rowOffset + rowOffsetRate
End Function
Private Function CheckSht(path As String, file As String) As String
Dim wb As Workbook
Dim okSheet As Boolean
If Right(path, 1) <> "\" Then path = path & "\"
On Error Resume Next
Set wb = Workbooks(file)
On Error GoTo 0
okSheet = wb Is Nothing
If Not okSheet Then okSheet = wb.path & "\" <> path
If Not okSheet Then
' file is already open
CheckSht = "workbook:" & vbCrLf & vbCrLf & file & vbCrLf & vbCrLf & "in:" & vbCrLf & vbCrLf & path & vbCrLf & vbCrLf & "is already open!"
Else
'Let’s check whether the file exists
If Dir(path & file) = "" Then CheckSht = "workbook:" & vbCrLf & vbCrLf & file & vbCrLf & vbCrLf & "in:" & vbCrLf & vbCrLf & path & vbCrLf & vbCrLf & "not found!"
End If
End Function
the "logic" of shifting to a different cell is all in var = GetFirstNonEmptyValueFromClosedWorkbook(a, argPart, -1) where that -1 is the "rowOffsetRate" that GetFirstNonEmptyValueFromClosedWorkbook(ref As String, argPart As String, Optional rowOffsetRate As Variant) As Variantfunction takes into account if the cell in address a is empty. if no "rowOffsetRate" is passed then it only checks the cell in address a