Saturday, December 19, 2015

Rename files in a folder using VBScript

Like a lot of you, I take a lot of pictures with my cell phone which I like to upload to my desktop computer. Besides pictures from the cell phone, I also have a Canon PowerShot camera that I like to use as well. When I upload the pictures, I like to have easier control of how the files are named for sharing purposes. Below is a VBScript I use to rename an entire folder's worth of pictures. For ease-of-use, I use textboxes to enter the folder path and the filename prefix. The script then adds unique numbers, with leading zeroes, to preserve the current sort. It's written to handle up to 9999 files in a folder, which for all practical purposes, is enough.

Option Explicit

Dim folderPath
Dim filePrefix
Dim FSO
Dim FLD
Dim file
Dim oldFilename
Dim newFilename
Dim LeadingZeroString
Dim count
Dim uniqueNumber

On Error Resume Next
folderPath = InputBox("Enter the folder path where your files are located:") 
filePrefix = InputBox("Enter the new filename prefix:") 

' path needs to end with a path separator
If Right(folderPath,1) <> "\" Then
folderPath = folderPath & "\"
End If

' Replace any characters, illegal or otherwise. 
filePrefix = Replace(Replace(filePrefix," ","_"),"\","_")

Set FSO = CreateObject("Scripting.FileSystemObject")
Set FLD = FSO.GetFolder(folderPath) 
If Err.Number < 1 Then
' set the correct # of leading zeros based on number of files
If FLD.Files.Count > 999 Then 
   LeadingZeroString = "0000"         
Elseif FLD.Files.Count > 99 Then 
   LeadingZeroString = "000" 
Else
   LeadingZeroString = "00" 
End If

'loop through the file collection, renaming files
For Each file in FLD.Files
   oldFilename = file.Path
   count = count + 1
   uniqueNumber = Right(LeadingZeroString & CStr(count), Len(LeadingZeroString))
   newFilename = folderPath & filePrefix & "_" & uniqueNumber & "." & FSO.GetExtensionName(oldFilename) 
   'rename the file
   FSO.MoveFile oldFilename, newFilename
Next

Set FLD = Nothing
Set FSO = Nothing
Else
MsgBox (Err.Description)
End If

Wednesday, July 8, 2015

Recently I updated a few MS Access reports that used various grouping; by day, by week and by month. In the group footers I needed to add two textboxes to display visit counts by campus.  Below is the report, group by week.





To show the first day of each week, the following expression was placed in the group header:

=Format([Time_In]-Weekday([Time_In],2),"dd-mmm-yyyy")

To show the count for the campuses, I included the following expressions:

=Count(IIf([Campus]="Pecos" Or IsNull([Campus]),1,Null))
and
=Count(IIf([Campus]="Williams",1,Null))

I look for null value because the Williams campus is a recent addition and there exists records where campus is null. I could have also summed the results as with the following expression:

=Sum(IIf([Campus]="Pecos" Or IsNull([Campus]),1,0))





Tuesday, March 17, 2015

Exporting Crystal Report to XML

Saving a Crystal Report in XML format, based upon the default Crystal Report schema, along with an xsl transformation, is a great way to  create web-ready content.

Below is a snippet of xml generated by Crystal Reports. While in Crystal, go to Format Field to set a custom Name attribute as shown below:

<?xml version="1.0" encoding="UTF-8" ?>
<CrystalReport xmlns="urn:crystal-reports:schemas:report-detail"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:crystal-reports:schemas:report-detail http://www.businessobjects.com/products/xml/CR2008Schema.xsd">
<Group Level="1">
<GroupHeader>
<Section SectionNumber="0">
<Field Name="TERM" FieldName="GroupName ({Command.CLASS_TERM_CD})"><FormattedValue>Spring 2015</FormattedValue><Value>Spring 2015</Value></Field>
<Field Name="TERMCODE" FieldName="{Command.CLASS_TERM_CD}"><FormattedValue>4152</FormattedValue><Value>4152</Value></Field>
</Section>
</GroupHeader>
<Details Level="2">
<Section SectionNumber="0">
<Field Name="CLASSNAME" FieldName="{Command.CLASS_CLASS_NAME}"><FormattedValue>ENG102</FormattedValue><Value>ENG102</Value></Field>
<Field Name="CLASSNBR" FieldName="{Command.CLASS_CLASS_NBR}"><FormattedValue>38090</FormattedValue><Value>38090</Value></Field>
<Field Name="TITLE" FieldName="{Command.CRSE_COURSE_TITLE_LONG}"><FormattedValue>First-Year Composition</FormattedValue><Value>First-Year Composition</Value></Field>
<Field Name="STARTTIME" FieldName="{Command.CLASS_START_TIME1}"><FormattedValue> 4:00PM</FormattedValue><Value> 4:00PM</Value></Field>
<Field Name="ENDTIME" FieldName="{Command.CLASS_END_TIME1}"><FormattedValue> 6:40PM</FormattedValue><Value> 6:40PM</Value></Field>
<Field Name="STARTDATE" FieldName="{Command.CLASS_START_DATE}"><FormattedValue>3/24</FormattedValue><Value>2015-03-24T00:00:00</Value></Field>
<Field Name="ENDDATE" FieldName="{Command.CLASS_END_DATE}"><FormattedValue>5/15</FormattedValue><Value>2015-05-15T00:00:00</Value></Field>
<Field Name="DAYS" FieldName="{@FormattedDays}"><FormattedValue>Tu,Tr</FormattedValue><Value>Tu,Tr</Value></Field>
</Section>
</Details>

...


On the XSL side, make sure you setup your Crystal Reports namespace. In the example below I'm using a 'cr' prefix.

<?xml version="1.0"?><xsl:stylesheet xmlns:cr="urn:crystal-reports:schemas:report-detail" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/">

<xsl:for-each select="cr:CrystalReport/cr:Group">

<h2 class="ms-rteElement-H2Custom"><xsl:value-of select="cr:GroupHeader/cr:Section/cr:Field[@Name='TERM']/cr:FormattedValue"/></h2><table width="100%" class="courseTableWP">
<xsl:for-each select="cr:Details/cr:Section">

<tr class="courseTableRow"></tr></xsl:for-each></table>
<th width="10%">Course</th><th width="15%">Class Number</th><th width="35%">Title</th><th width="10%">Days</th><th width="15%">Times</th><th width="15%">Dates</th>
<td><xsl:value-of select="cr:Field[@Name='CLASSNAME']/cr:FormattedValue"/></td>
<td><xsl:value-of select="cr:Field[@Name='CLASSNBR']/cr:FormattedValue"/></td>
<td><xsl:value-of select="cr:Field[@Name='TITLE']/cr:FormattedValue"/></td>
<td><xsl:value-of select="cr:Field[@Name='DAYS']/cr:FormattedValue"/></td>
<td><xsl:value-of select="cr:Field[@Name='STARTTIME']/cr:FormattedValue"/>- <xsl:value-of select="cr:Field[@Name='ENDTIME']/cr:FormattedValue"/></td>
<td><xsl:value-of select="cr:Field[@Name='STARTDATE']/cr:FormattedValue"/> - <xsl:value-of select="cr:Field[@Name='ENDDATE']/cr:FormattedValue"/></td>

</xsl:for-each>
</xsl:template>
</xsl:stylesheet>