From ce79ecfbc4ad73f533fd7523d11c040bef346789 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 18 Jan 2020 07:31:35 -0500 Subject: [PATCH 1/3] Add controls and UI logic for header rows feature Functionality to actually export the header rows, and to indicate in the export status box that the header is being exported, still needs implementation. Part of #22. --- src/UFExporter.frm | 93 ++++++++++++++++++++++++++++++++++++++++++++- src/UFExporter.frx | Bin 4120 -> 4632 bytes 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/UFExporter.frm b/src/UFExporter.frm index 7caeb2e..879909c 100644 --- a/src/UFExporter.frm +++ b/src/UFExporter.frm @@ -1,7 +1,7 @@ VERSION 5.00 Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UFExporter Caption = "Export Data Range" - ClientHeight = 4770 + ClientHeight = 5730 ClientLeft = 45 ClientTop = 375 ClientWidth = 4560 @@ -15,6 +15,7 @@ Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False + ' # ------------------------------------------------------------------------------ ' # Name: UFExporter.frm ' # Purpose: Core UserForm for the CSV Exporter Excel VBA Add-In @@ -47,6 +48,7 @@ Dim WorkFolder As Folder Dim fs As FileSystemObject Dim ExportRange As Range Dim HiddenByChart As Boolean +Dim wsf As worksheetfunction ' ===== EVENT-ENABLED APPLICATION EVENTS ===== @@ -222,6 +224,33 @@ Private Sub BtnSelectFolder_Click() End Sub +Private Sub ChBxHeaderRows_Change() + ' Set the header rows box colors appropriately + setHeaderTBxColors + + ' Update Export button + setExportEnabled + +End Sub + +Private Sub TBxHeaderStart_Change() + ' Set header rows box colors + setHeaderTBxColors + + ' Update export button + setExportEnabled + +End Sub + +Private Sub TBxHeaderStop_Change() + ' Set header rows box colors + setHeaderTBxColors + + ' Update export button + setExportEnabled + +End Sub + Private Sub TxBxFilename_Change() ' If filename is nonzero-length and valid, set color black. @@ -280,6 +309,9 @@ Private Sub UserForm_Initialize() ' General is default number format TxBxFormat.Value = "@" + ' Bind the worksheet function object + Set wsf = Application.worksheetfunction + End Sub @@ -294,7 +326,8 @@ Private Sub setExportEnabled() validFilename(TxBxFilename.Value) And _ Len(TxBxFormat.Value) > 0 And _ (Not WorkFolder Is Nothing) And _ - (Not ExportRange Is Nothing) _ + (Not ExportRange Is Nothing) And _ + (Not (ChBxHeaderRows.Value And Not checkHeaderRowValues)) _ ) Then BtnExport.Enabled = True Else @@ -361,7 +394,62 @@ Private Function getExportRangeAddress() As String End Function +Private Function checkHeaderRowValues() As Boolean + ' Proofreads the values in the row start/stop for the header inclusion + ' + ' True means values are ok (numbers, and start <= stop + ' False means something (unspecified) is wrong; + ' could be non-numeric, or start > stop + + Dim errNum As Long, startRow As Long, stopRow As Long + Dim startStr As String, stopStr As String + + ' Cope with empty textboxes + If TBxHeaderStart.Value = "" Then + startStr = "0" + Else + startStr = TBxHeaderStart.Value + End If + + If TBxHeaderStop.Value = "" Then + stopStr = "0" + Else + stopStr = TBxHeaderStop.Value + End If + + ' Default to failure + checkHeaderRowValues = False + + On Error Resume Next + startRow = CInt(startStr) + stopRow = CInt(stopStr) + errNum = Err.Number: Err.Clear: On Error GoTo 0 + + ' One or more non-numeric values + If errNum <> 0 Then Exit Function + + ' Might as well make it so an empty start row means row 1 + startRow = Application.worksheetfunction.Max(1, startRow) + + ' Value check + If startRow > stopRow Then Exit Function + + ' Checks ok; return True + checkHeaderRowValues = True + +End Function +Private Sub setHeaderTBxColors() + ' Helper encapsulating the color setting logic + If checkHeaderRowValues Then + TBxHeaderStart.ForeColor = RGB(0, 0, 0) + TBxHeaderStop.ForeColor = RGB(0, 0, 0) + Else + TBxHeaderStart.ForeColor = RGB(255, 0, 0) + TBxHeaderStop.ForeColor = RGB(255, 0, 0) + End If + +End Sub ' ===== HELPER FUNCTIONS ===== Private Sub writeCSV(dataRg As Range, tStrm As TextStream, nFormat As String, _ @@ -455,3 +543,4 @@ Private Function isSeparatorInData(dataRg As Range, nFormat As String, _ Next cel End Function + diff --git a/src/UFExporter.frx b/src/UFExporter.frx index 2970e5059903cf9a5114b7e4cb49058c44df6b8c..bc8ec534c64c6802532a9aae46d22effd88aad80 100644 GIT binary patch delta 1062 zcmZ8gOH30{6umQ@mQI-|zfu}Pv6NraNJRW$HDW*rF+>e?L4q2p9l=mKwG<^1)7iN* z;x(Zg7jBe@3yg8&iY*#-Wn$t&6Qc`PCdQS$4F@<)a5xUbi=V=wFMlY|)Lu%|BoEvf?oKt1pq1~}(wYH7yHE+7K5 z08yY7XafYP1J-7wW>VV7t5s`3ESJkfJ&1IJXa>29oqW*SrHP~0gz38yvFU9Okx7Fj zhbSf!d5EmRg`Al$5br{@c~`9fs)ayo5fBctZExxQt-tu{+X z`He5k!AI)u#~{2IKS z1?n7raWi4S%*>_f7u5ex5EpwK(EbY89TfsbMl`A@Zu|}baZ~pLIyF!der)4?6~cM49DCGy3M7fF7nVkaqSn&)8G{wy{HkZ*}wC%9Gr3Ya+vC~#Y>-}-V(RTi%) IF?`#hKN7X(jsO4v delta 707 zcmYLHL1+_E5S{(In`Sq=o2HGMQj<1WBZg?u29;XGKw~9HK!_d+EyZZoC~mSbO*9D7 z+`MUZ4))?z1wAN5&w8vEPlbX|FM5gxK?Lc+IDgaXhqsSE|IPe2e|9ao7B`Etet=fRqHkHmrr{ ztltMn5yL%zo09ZkmH&h| z;1p^~Hrlg18Kn-9?40XV?BisO? zziv^@a`~!ivRWBmsJG1=>{aI`F4~TLwH2t62`d?>0*iaS82|j~YN=eW+A{#R$juj# z8xV5%B(P*s{)Kj{(Qd^HH!2mo9xu6fmUH+}*)OY9=`?;)V_491{`@$vrMZzQDJ+x0 zSQMY?X-2f6r&zm&KlO~*BtBp)2sW-5X=dB_(#VJ{;?Kq*!9p?URX9pSv4!9zLBrR< z$V!0^3y#1q8exEZ2Wgij93$v7!QvHX@YJPh@gqH$ysQ64dfq1=)MbJJ Date: Mon, 3 Feb 2020 13:18:10 -0500 Subject: [PATCH 2/3] Implement actual header export Working on #22. Believe implementation is complete, but could use testing. --- src/UFExporter.frm | 89 ++++++++++++++++++++++++++++++++++++++++++--- src/UFExporter.frx | Bin 4632 -> 4632 bytes 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/UFExporter.frm b/src/UFExporter.frm index 879909c..94c8938 100644 --- a/src/UFExporter.frm +++ b/src/UFExporter.frm @@ -1,7 +1,7 @@ VERSION 5.00 Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UFExporter Caption = "Export Data Range" - ClientHeight = 5730 + ClientHeight = 5955 ClientLeft = 45 ClientTop = 375 ClientWidth = 4560 @@ -16,6 +16,7 @@ Attribute VB_PredeclaredId = True Attribute VB_Exposed = False + ' # ------------------------------------------------------------------------------ ' # Name: UFExporter.frm ' # Purpose: Core UserForm for the CSV Exporter Excel VBA Add-In @@ -41,6 +42,7 @@ Attribute appn.VB_VarHelpID = -1 ' ===== CONSTANTS ===== Const NoFolderStr As String = "" Const InvalidSelStr As String = "" +Const NoHeaderRngStr As String = "" ' ===== GLOBALS ===== @@ -176,7 +178,14 @@ Private Sub BtnExport_Click() End If ' Ready to go. Pass info to writing function - writeCSV ExportRange, tStrm, TxBxFormat.Value, TxBxSep.Value + ' Header first (always exporting, even if hidden; but only if enabled)... + If ChBxHeaderRows.Value Then + writeCSV dataRg:=getHeaderRange, tStrm:=tStrm, nFormat:=TxBxFormat.Value, _ + Separator:=TxBxSep.Value, overrideHidden:=True + End If + ' ... then body (obeying 'hidden cell export' settings) + writeCSV dataRg:=ExportRange, tStrm:=tStrm, nFormat:=TxBxFormat.Value, _ + Separator:=TxBxSep.Value, overrideHidden:=False ' Close the stream tStrm.Close @@ -228,6 +237,9 @@ Private Sub ChBxHeaderRows_Change() ' Set the header rows box colors appropriately setHeaderTBxColors + ' Update the range report box + setExportRangeText + ' Update Export button setExportEnabled @@ -237,6 +249,9 @@ Private Sub TBxHeaderStart_Change() ' Set header rows box colors setHeaderTBxColors + ' Update the range report box + setExportRangeText + ' Update export button setExportEnabled @@ -246,6 +261,9 @@ Private Sub TBxHeaderStop_Change() ' Set header rows box colors setHeaderTBxColors + ' Update the range report box + setExportRangeText + ' Update export button setExportEnabled @@ -371,6 +389,9 @@ Private Sub setExportRangeText() workStr = " Worksheet: " _ & Selection.Parent.Name _ & Chr(10) _ + & " Header: " _ + & getHeaderRangeAddress _ + & Chr(10) _ & " Range: " _ & getExportRangeAddress @@ -394,10 +415,68 @@ Private Function getExportRangeAddress() As String End Function +Private Function getHeaderRangeAddress() As String + ' Helper for concise generation of the header range address + ' without dollar signs. + ' + ' Or, if header export is deselected, report accordingly + + If ChBxHeaderRows.Value Then + If checkHeaderRowValues Then + getHeaderRangeAddress = getHeaderRange.Address( _ + RowAbsolute:=False, ColumnAbsolute:=False _ + ) + Else + getHeaderRangeAddress = InvalidSelStr + End If + Else + getHeaderRangeAddress = NoHeaderRngStr + End If + +End Function + +Private Function getHeaderRange() As Range + ' Helper to actually generate a reference to the header range, + ' given the currently set export range. + ' + ' If any of the form is in a state where the header range + ' can't be defined, returns Nothing. + + Dim headerFullRows As Range + Dim startRow As Long, stopRow As Long + Dim errNum As Long + + Set getHeaderRange = Nothing + + If Not ChBxHeaderRows.Value Then Exit Function + If Not checkHeaderRowValues Then Exit Function + If ExportRange Is Nothing Then Exit Function + + ' Handle the case where the start value is blank (implicit start at '1') + On Error Resume Next + startRow = CLng(TBxHeaderStart.Value) + errNum = Err.Number: Err.Clear: On Error GoTo 0 + + Select Case errNum + Case 13 + startRow = 1 + End Select + + ' Stop row shouldn't(?) need special handling, given that it's already + ' proofed by the above checks + stopRow = CLng(TBxHeaderStop.Value) + + Set headerFullRows = ExportRange.Worksheet.Rows(startRow) + Set headerFullRows = headerFullRows.Resize(stopRow - startRow + 1) + + Set getHeaderRange = Intersect(ExportRange.EntireColumn, headerFullRows) + +End Function + Private Function checkHeaderRowValues() As Boolean ' Proofreads the values in the row start/stop for the header inclusion ' - ' True means values are ok (numbers, and start <= stop + ' True means values are ok (numbers, and start <= stop) ' False means something (unspecified) is wrong; ' could be non-numeric, or start > stop @@ -453,7 +532,7 @@ End Sub ' ===== HELPER FUNCTIONS ===== Private Sub writeCSV(dataRg As Range, tStrm As TextStream, nFormat As String, _ - Separator As String) + Separator As String, overrideHidden As Boolean) ' Encapsulates the process of actually writing the selected data to ' CSV on-disk. @@ -475,7 +554,7 @@ Private Sub writeCSV(dataRg As Range, tStrm As TextStream, nFormat As String, _ ' Loop For idxRow = 1 To dataRg.Rows.Count ' Only output visible rows unless hidden output indicated - If ChBxHiddenRows.Value Or Not dataRg.Cells(idxRow, 1).EntireRow.Hidden Then + If overrideHidden Or ChBxHiddenRows.Value Or Not dataRg.Cells(idxRow, 1).EntireRow.Hidden Then ' Reset the working string workStr = "" diff --git a/src/UFExporter.frx b/src/UFExporter.frx index bc8ec534c64c6802532a9aae46d22effd88aad80..94a2bbb2571bd1fe90bb29c5a23960fdce1814e7 100644 GIT binary patch delta 388 zcmbQCGDBs82vd*bMzK5=HiNI;Hv4XE?qXTR%*3HN*^I-2QDJgEhZ<99?&Rql_a{ej z2~FitINX<*JXP!KPQ*N>n zw}}eSSSAIqWqd%(Tq_Fli%NL8f)ex6K{gh$Gcep|2AeyLTZritD~QPo(&I4sJeTa` z7u?E|`#Gh-A~s+V4<24-pgof#c(w@vX(kb{*-SvQOY$@FCoAw)GbO4_p3AERqE7N^ zfIR=1SC_fGSYfgAVh8{L delta 377 zcmXX?ze@sP7=FL+uDtv1hd;0gB#~26EOm(}2`s2+XtE`8I`F7K?=x`-912>ZA%b^M zg61Hn5E`0VC8|H5!JwtFa0!CwJ8OD)AD$n)Pdm|0oQG*=;%3~HM?abm$?wPRseCQb zW)kO=c>>6lDarv`N*}jb2v1ZC&lnq10gl%8DvoPcojh>pjQ}j*ryj>wUB@rg64nTd zFdJ4BfGYxk_xcQ0Sf2ff|EVZGv1!fT<;%62f+$(SXEurNTAZ}JB(gZX*L6b@9k`|6h6*A#Jj|sc zx50%mW;E%Yg_lO!gPxJ1?hX!&j06r~+$@P-4$U;J+SoA#Ddu=Fi^7dLf7% Date: Mon, 3 Feb 2020 13:24:24 -0500 Subject: [PATCH 3/3] Update CHANGELOG and copyright year range --- CHANGELOG.md | 7 ++++++- LICENSE.txt | 2 +- README.md | 2 +- src/Exporter.bas | 2 +- src/UFExporter.frm | 2 +- src/UFExporter.frx | Bin 4632 -> 4632 bytes 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af5d16c..5a157e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -### [Unreleased] +### [1.2.0.dev1] - 2020-02-03 + +Development release issued, to facilitate user testing before considering +the below new features as "final". #### Added - Hidden rows and columns now are **NOT** exported by default; checkboxes to enable export of hidden cells (per row and/or per-column) are now provided +- An option is now provided to export the cells from one or more rows on + the active sheet above/below the exported data block as "header row(s)" ### [1.1.0] - 2019-01-08 diff --git a/LICENSE.txt b/LICENSE.txt index a6e6c15..f35ea56 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2019 Brian Skinn +Copyright (c) 2016-2020 Brian Skinn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4d8c53c..ecf012d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ See the project [wiki](https://github.com/bskinn/excel-csvexporter/wiki) for doc The binary `.xlam` file for each release can be found on the GitHub page for that release. -Copyright (c) Brian Skinn 2016-2019 +Copyright (c) Brian Skinn 2016-2020 License: The MIT License See [`LICENSE.txt`](https://github.com/bskinn/excel-csvexporter/blob/master/LICENSE.txt) for full license terms. diff --git a/src/Exporter.bas b/src/Exporter.bas index 4f163df..eb7373b 100644 --- a/src/Exporter.bas +++ b/src/Exporter.bas @@ -8,7 +8,7 @@ Attribute VB_Name = "Exporter" ' # bskinn@alum.mit.edu ' # ' # Created: 24 Jan 2016 -' # Copyright: (c) Brian Skinn 2016-2019 +' # Copyright: (c) Brian Skinn 2016-2020 ' # License: The MIT License; see "LICENSE.txt" for full license terms. ' # ' # http://www.github.com/bskinn/excel-csvexporter diff --git a/src/UFExporter.frm b/src/UFExporter.frm index 94c8938..2b8565b 100644 --- a/src/UFExporter.frm +++ b/src/UFExporter.frm @@ -25,7 +25,7 @@ Attribute VB_Exposed = False ' # bskinn@alum.mit.edu ' # ' # Created: 24 Jan 2016 -' # Copyright: (c) Brian Skinn 2016-2019 +' # Copyright: (c) Brian Skinn 2016-2020 ' # License: The MIT License; see "LICENSE.txt" for full license terms. ' # ' # http://www.github.com/bskinn/excel-csvexporter diff --git a/src/UFExporter.frx b/src/UFExporter.frx index 94a2bbb2571bd1fe90bb29c5a23960fdce1814e7..3441a8c8a8d2f980659cf32c670b98a4c9baf460 100644 GIT binary patch delta 349 zcmbQCGDBrU3k&OqMt$4;n>$&aGBbXfoX?@kTwbg&c{+zVQ*Qa>3mms5_i=Ge-ok0b z)DSiK1*Z`s!(?eLX|7o^E*uOD%NZFMCLiF@nViFA1>~M&1qn^=XmCpEbQXu}!~C6$IK1||it6dzE^wW1)usDzg* zC^0WR)ha=ukez|yJ~P-<`>4q?xb;{=WEhwnCZFe$o&18^4rnI>lMR^X!NV(@n33<1 znUa#4r{J8QQ<|GsY_9-xq1@y)o;@HB-Qh8vT*+I(1a$XjUR`FO-pR^*(Lhht^Jy_9 zC`?|>2NAr@rw$Zk=GOwL)Q3>f{L>jzCx7PGW721ytSq1hQXdSVnt>Eh;bsAS#{A8X H1xy(McjRDH delta 346 zcmbQCGDBrU3k$2kS8tnrn>$&aGBYYn&gW2NW+=^_Je|XwiGgAA1&&)xVa$`)a9V+= z7o0|nR+FWM;g$XfPF-$(grOVC0z~ER=keZib z&pdeoryRcog9cEDje(&dI5j6VdGbmQRTV1+1||itI3G~lwW1)usDzg*C^0WR6)086 z&cJY=8DtH}%o*HztRVFclh1R>PJY2{2jvN_)nzU(R+y~J7tP2#xt>o8 zsWYZdX6DyoDoCBI52W;&Cr9&7XUv)WnO~0yq)R{#Bo+*$@^dFQL#WLH`iwc79}Ac= F0swgETp$1d