Copy and Rename File VB Script Not Working For SSIS Script Task - vb.net

I am dynamically creating reports using an Excel Template for an SSIS Package. I am attempting to copy the Excel template and rename it using VB 2010 in Script Task object.
The following is my code:
Public Sub Main()
Dim sourcePath As String = "\\server\Dir1\Dir2\Dir3\FileName_TEMPLATE.xlsx"
Dim destPath As String = "\\server\Dir1\Dir2\Dir3\FileName" + CDate(Date.Today.Date).ToString("yyyyMMdd") + ".xlsx"
If File.Exists(destPath) = True Then
File.Delete(destPath) 'delete existing file'
File.Copy(sourcePath, destPath) 'copy template file and rename'
End If
Dts.TaskResult = ScriptResults.Success
End Sub
End Class
I changed If File.Exists(destPath) = True Then... to If File.Exists(sourcePath) = True... to see if the sourcePath existed and then added a MessageBox("File doesn't exist") in an ELSE statement to so if even the source file exists and it is returning the MessageBox stating
"File doesn't exist"
The Template file is there and I copied and pasted the address from Windows Explorer window to the sourcePath string to ensure path accuracy.
The sourcePath is on a different server.
The file is in the source path.
What am I doing wrong?
Thanks

Related

SSIS Script Task - VB looping issue

The following script task in SSIS connects to a FTP server and is supposed to look for a file until it exists, then copy that file to a local folder. It's doing everything correctly but instead of looking for the specific file, it's copying ALL files.
I've pieced the script together from various forums as I'm not a VB writer. It appears the fileName.Contains is being ignored.
Any help would be great. Thanks!
' Microsoft SQL Server Integration Services Script Task
' Write scripts using Microsoft Visual Basic 2008.
' The ScriptMain is the entry point class of the script.
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
<Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute>
<System.CLSCompliantAttribute(False)>
Partial Public Class ScriptMain
Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
Enum ScriptResults
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
End Enum
Public Sub Main()
System.Threading.Thread.Sleep(50000)
Dim VarCol As Variables = Nothing
Dts.VariableDispenser.LockForWrite("User::FileFound")
Dts.VariableDispenser.LockForWrite("User::FileName")
Dts.VariableDispenser.GetVariables(VarCol)
Try
'Create the connection to the ftp server
Dim cm As ConnectionManager = Dts.Connections.Add("FTP")
Dim strFolders As String()
Dim strFiles As String()
Dim fileCount As Int32
fileCount = 0
Dim fileName As String
'Set the properties like username & password
cm.Properties("ServerName").SetValue(cm, "ftp.testing.com")
cm.Properties("ServerUserName").SetValue(cm, "username") 'user name
cm.Properties("ServerPassword").SetValue(cm, "password") 'password
Dim ftp As FtpClientConnection = New FtpClientConnection(cm.AcquireConnection(Nothing))
'Connects to the ftp server
ftp.Connect()
ftp.SetWorkingDirectory("/testing")
ftp.GetListing(strFolders, strFiles)
For Each fileName In strFiles
If fileName.Contains("test.xml") Then 'file has such word in its name
ftp.ReceiveFiles(strFiles, "\\FTPSERVER\c$\FTP FILES\testing", True, False) 'download file if found
fileCount = fileCount + 1
VarCol("User::FileFound").Value = fileName
VarCol("User::FileFound").Value = True
Else
VarCol("User::FileFound").Value = False
End If
Next
ftp.Close()
VarCol.Unlock()
Catch ex As Exception
Dts.TaskResult = ScriptResults.Failure
End Try
Dts.TaskResult = ScriptResults.Success
End Sub
End Class
Ok, I am not up on VB code so the syntax is most likely not right but the logic here should do what you need (you will just have to update to match VB syntax). I put comments in the code to show what I am doing and also a problem with returning one of the file names in your current logic (I did not fix that I just pointed it out).
//declare string array to pass to your FTP call for only matching fiels
Dim FileNameListMatching as String()
For Each fileName In strFiles
If fileName.Contains("test.xml") Then 'file has such word in its name
// then if the file name matches in the if above, add that filename at the fileCount location into the string array
FileNameListMatching(fileCount) = fileName
fileCount = fileCount + 1
// this will have a problem here though because you are populating a variable with the fileName, but if there is more then 1 fileName found in your logic, it will overwrite it with only the most recent file name. The True value is fine, because you dont care if there is more then 1 for that, but the file name returned will only give you the most recent file name if more then 1
VarCol("User::FileFound").Value = fileName
VarCol("User::FileFound").Value = True
Else
VarCol("User::FileFound").Value = False
End If
Next
-- then if filecount is > 0 then call your FTP to copy files
if fileCount > 0
ftp.ReceiveFiles(FileNameListMatching, "\\FTPSERVER\c$\FTP FILES\testing", True, False) 'download file if found

Convert multiple .xls files to .xlsx in ssis

I have a folder that receives multiple excel files in .xls format. I need to change the format type to .xlsx in order to load the excel data into SQLvia SSIS. I know how to rename the file using "File System Task" but that works for a specific file. but my file contains a file # and date as well that needs to stay same as source file, I only want the file type to change and the file move to a processed folder. Can anyone help me?
Source Path: C:\Documents\TestFolder
Source File: TestSegRpt_0001_2017_02_22.xls
Destination Path: C:\Documents\TestFolderProcessed
Destination File: TestSegRpt_0001_2017_02_22.xlsx
Hoping i understood your problem correctly.
I think below link will help.
https://answers.microsoft.com/en-us/msoffice/forum/msoffice_excel-mso_other/batch-convert-xls-to-xlsx/1d9b3d78-daf0-4014-8fb2-930aca6493b0
You have to add a Script Task, loop over files, and use a function like the following to create precessed directory and convert files (code in Vb.net):
Public Sub ConvertXlsToXlsx(ByVal strpath as string)
Dim strDirectory as string = System.IO.Path.GetDirectoryName(strpath) & "Processed"
If Not System.IO.Directory.Exists(strDirectory) Then System.IO.Directory.CreateDirectory(strDirectory)
Dim xl As New Microsoft.Office.Interop.Excel.Application
Dim xlBook As Microsoft.Office.Interop.Excel.Workbook
xlWorkBook = xl.Workbooks.Open(strpath)
xlBook.SaveAs(strDirectory & "\" & System.IO.Path.GetFilename(strpath) & "x")
xl.Application.Workbooks.Close()
xl.Application.Quit()
End Sub
Your code will look like:
Public Sub Main
Dim strFolder as string = Dts.Variables.Item("FolderPath").Value
Dim strXlsFiles() as string = IO.Directory.GetFiles(strFolder,"*.xlsx",SearchOption.TopDirectoryOnly)
For each strFile as String in strXlsFiles
If strFile.EndsWith("xlsx") The Continue For
ConvertXlsToXlsx(strFile)
Next
End Sub
Reference:
https://social.msdn.microsoft.com/Forums/office/en-US/a73f846c-91ee-4dad-bd7b-c04d418d0561/convert-xls-into-xlsx?forum=exceldev

How to Access a txt file in a Folder created inside a VB project

I'm creating a VB project for Quiz App (in VS 2013). So I have some preset questions which are inside the project (I have created a folder inside my project and added a text file).
My question is how can I read and write contents to that file? Or if not is there any way to copy that txt file to Documents/MyAppname when installing the app so that I can edit it from that location?
In the example below I am focusing on accessing files one folder under the executable folder, not in another folder else wheres. Files are read if they exists and then depending on the first character on each line upper or lower case the line then save data back to the same file. Of course there are many ways to work with files, this is but one.
The following, created in the project folder in Solution Explorer a folder named Files, add to text files, textfile1.txt and textfile2.txt. Place several non empty lines in each with each line starting with a character. Each textfile, set in properties under solution explorer Copy to Output Directory to "Copy if newer".
Hopefully this is in tune with what you want. It may or may not work as expected via ClickOnce as I don't use ClickOnce to validate this.
In a form, one button with the following code.
Public Class Form1
Private TextFilePath As String =
IO.Path.Combine(
AppDomain.CurrentDomain.BaseDirectory, "Files")
Private TextFiles As New List(Of String) From
{
"TextFile1.txt",
"TextFile2.txt",
"TextFile3.txt"
}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim FileName As String = ""
' loop thru each file
For Each fileBaseName As String In TextFiles
FileName = IO.Path.Combine(TextFilePath, fileBaseName)
' only access file if it exist currently
If IO.File.Exists(FileName) Then
' read file into string array
Dim contents As String() = IO.File.ReadAllLines(FileName)
' upper or lower case line based on first char.
' this means you can flip flop on each click on the button
For x As Integer = 0 To contents.Count - 1
If Char.IsUpper(CChar(contents(x))) Then
contents(x) = contents(x).ToLower
Else
contents(x) = contents(x).ToUpper
End If
Next
' save changes, being pesstimistic so we use a try-catch
Try
IO.File.WriteAllLines(FileName, contents)
Catch ex As Exception
Console.WriteLine("Attempted to save {0} failed. Error: {1}",
FileName,
ex.Message)
End Try
Else
Console.WriteLine("Does not exists {0}", FileName)
End If
Next
End Sub
End Class
This may help you
Dim objStreamReader As StreamReader
Dim strLine As String
'Pass the file path and the file name to the StreamReader constructor.
objStreamReader = New StreamReader("C:\Boot.ini")
'Read the first line of text.
strLine = objStreamReader.ReadLine
'Continue to read until you reach the end of the file.
Do While Not strLine Is Nothing
'Write the line to the Console window.
Console.WriteLine(strLine)
'Read the next line.
strLine = objStreamReader.ReadLine
Loop
'Close the file.
objStreamReader.Close()
Console.ReadLine()
You can also check this link.

How to open file located inside winform project

I have a project that requires some pdf reports to be opened from my forms. Since the program can be installed in any drive, I used the winform location directory as my path. I reports are located on a directory called Reports. It works well under development becuase I the winform is under bin\debug, but when I deploy my solution and try the procedure, it does not work, the file cannot be found. I created a Reports directory after deployment, but still did not find my pdf.
Here is the code:
'Open the requested file name. The files are stored in the
'same path as the main workbook.
'#param filename file to be opened
Function OpenReports(strFileName As String) As String
Dim reportFolder As String
Try
reportFolder = Path.Combine(Directory.GetCurrentDirectory(), "Reports")
System.Diagnostics.Process.Start(reportFolder & "\" & strFileName)
Catch ex As Exception
MsgBox("The " & strFileName & " is not found on directory")
End Try
Return strFileName
End Function
Private Sub btnRptRangesToMarket_Click(sender As Object, e As EventArgs) Handles btnRptRangesToMarket.Click
'This procedure runs when the btnRptRangesToMarket is clicked
'the procedure opens the pdf below by running the OpenReports Function
OpenReports("Ranges to Market.pdf")
End Sub
Try Application.StartupPath instead of Directory.GetCurrentDirectory(). I always get good results with that property.
This is from MSDN:
The current directory is distinct from the original directory, which is the one from which the process was started.

AutoUpdate VBA startup macro?

I'm building some Word 2003 macro that have to be put in the %APPDATA%\Microsoft\Word\Startup folder.
I can't change the location of this folder (to a network share). How can I auto update this macros ?
I have tried to create a bootstrapper macro, with an AutoExec sub that copy newer version from a file share to this folder. But as Word is locking the file, I get a Denied Exception.
Any idea ?
FYI, I wrote this code. The code is working fine for update templates in templates directory, but not in startup directory :
' Bootstrapper module
Option Explicit
Sub AutoExec()
Update
End Sub
Sub Update()
MirrorDirectory MyPath.MyAppTemplatesPath, MyPath.WordTemplatesPath
MirrorDirectory MyPath.MyAppStartupTemplatesPath, MyPath.WordTemplatesStartupPath
End Sub
' IOUtilities Module
Option Explicit
Dim fso As New Scripting.FileSystemObject
Public Sub MirrorDirectory(sourceDir As String, targetDir As String)
Dim result As FoundFiles
Dim s As Variant
sourceDir = RemoveTrailingBackslash(sourceDir)
targetDir = RemoveTrailingBackslash(targetDir)
With Application.FileSearch
.NewSearch
.FileType = MsoFileType.msoFileTypeAllFiles
.LookIn = sourceDir
.SearchSubFolders = True
.Execute
Set result = .FoundFiles
End With
For Each s In result
Dim relativePath As String
relativePath = Mid(s, Len(sourceDir) + 1)
Dim targetPath As String
targetPath = targetDir + relativePath
CopyIfNewer CStr(s), targetPath
Next s
End Sub
Public Function RemoveTrailingBackslash(s As String)
If Right(s, 1) = "\" Then
RemoveTrailingBackslash = Left(s, Len(s) - 1)
Else
RemoveTrailingBackslash = s
End If
End Function
Public Sub CopyIfNewer(source As String, target As String)
Dim shouldCopy As Boolean
shouldCopy = False
If Not fso.FileExists(target) Then
shouldCopy = True
ElseIf FileDateTime(source) > FileDateTime(target) Then
shouldCopy = True
End If
If (shouldCopy) Then
If Not fso.FolderExists(fso.GetParentFolderName(target)) Then fso.CreateFolder (fso.GetParentFolderName(target))
fso.CopyFile source, target, True
Debug.Print "File copied : " + source + " to " + target
Else
Debug.Print "File not copied : " + source + " to " + target
End If
End Sub
' MyPath module
Property Get WordTemplatesStartupPath()
WordTemplatesStartupPath = "Path To Application Data\Microsoft\Word\STARTUP"
End Property
Property Get WordTemplatesPath()
WordTemplatesPath = "Path To Application Data\Microsoft\Templates\Myapp\"
End Property
Property Get MyAppTemplatesPath()
MyAppTemplatesPath = "p:\MyShare\templates"
End Property
Property Get XRefStartupTemplatesPath()
MyAppStartupTemplatesPath = "p:\MyShare\startup"
End Property
[Edit] I explored another way
Another way I'm thinking about, is to pilot the organizer :
Sub Macro1()
'
' Macro1 Macro
' Macro recorded 10/7/2011 by beauge
'
Application.OrganizerCopy source:="P:\MyShare\Startup\myapp_bootstrapper.dot", _
Destination:= _
"PathToApplication Data\Microsoft\Word\STARTUP\myapp_bootstrapper.dot" _
, Name:="MyModule", Object:=wdOrganizerObjectProjectItems
End Sub
This is working, but has limitations :
either I have to hard-code modules to organize
or I have to change the option "Trust VBA project" to autodiscover items like this (which is not acceptable as it requires to lower the security of the station) :
the code of the project enumeration is this one :
Public Sub EnumProjectItem()
Dim sourceProject As Document
Dim targetProject As Document
Set sourceProject = Application.Documents.Open("P:\MyShare\Startup\myapp_bootstrapper.dot", , , , , , , , , wdOpenFormatTemplate)
Set targetProject = Application.Documents.Open("PathToApplication Data\Microsoft\Word\STARTUP\myapp_bootstrapper.dot", , , , , , , , , wdOpenFormatTemplate)
Dim vbc As VBcomponent
For Each vbc In sourceProject.VBProject.VBComponents 'crash here
Application.ActiveDocument.Range.InsertAfter (vbc.Name + " / " + vbc.Type)
Application.ActiveDocument.Paragraphs.Add
Next vbc
End Sub
[Edit 2] Another unsuccessful try :
I put, in my network share, a .dot with all the logic.
In my STARTUP folder, I put a simple .Dot file, that references the former one, with a single "Call MyApp.MySub".
This is actually working, but as the target template is not in a trusted location, a security warning is popped up each time word is launched (even if not related to the current application macro)
At least, I succeed partially using these steps :
Create a setup package. I use a NSIS script
the package detect any instance of Winword.exe and ask the user to retry when word is closed
extract from the registry the word's option path
deploy the files into the word's startup folder
add an uninstaller in the local user add/remove programs
I put the package in the remote share. I also added a .ini file containing the last version of the package (in the form "1.0")
In the macro itself, I have a version number ("0.9" for example).
At the startup (AutoExec macro), I compare the local version to the remote version
I use shell exec to fire the setup if a newer version is found.
The setup will wait for Word to close
A bit tricky, but it works on Word 2K3 and Word 2K10.