Sei sulla pagina 1di 9

5/1/2014 Daily Dose of Excel

http://dailydoseofexcel.com/ 1/9
Daily Dose of Excel
Excel tips and other stuff
Pop quiz
April 30, 2014, 10:01 pm by Jeff Weir
Question One
You want to calculate a running (i.e. cumulative) total of the Data column.
Which of these formulas should you put in B2 and drag down, and why?
=SUM(A$2:A2)
=SUM(A2,B1)
Question Two
You want to calculate a running (i.e. cumulative) total of the Data column, and subtract 1 from it.
Which of these formulas should you put in B2 and drag down, and why?
=SUM(A$2:A2)-1
=SUM(A2,B1)-1
edit
If youre ambivalent as to the approach you would take, whip up a sample file. Then you wont be ambivalent.
For Question one, Imagine youve got a really long list. Say a file with =row() in cells A1 to A20000.
For Question two, list length is unimportant, but be sure to do both approaches side by side.
In fact, lets assume a more realistic data set, where instead of subtracting 1 from the cumulative total, you want to subtract a
varying list of cumulative expenses, so you can work out the cumulative net profit:
Category: Uncategorized | 14 Comments
Copy Selection Sum to Clipboard
April 30, 2014, 6:30 am by Dick Kusleika
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 2/9
Last month I posted some metrics on the keyboard shortcuts I use. One of the pieces of code that I could not link to (because Ive
never posted it) is CopySum. I dont remember what prompted me to write this little procedure, but it has been surprisingly useful.
It sums the selected cells and puts that sum into the clipboard. Thats all it does.
Sub CopySum()

Dim doClip As MSForms.DataObject

On Error Resume Next

gclsAppEvents.AddLog "^+c", "CopySum"

Set doClip = New MSForms.DataObject

If TypeName(Selection) = "Range" Then
doClip.SetText Application.WorksheetFunction.Sum(Selection)
doClip.PutInClipboard
End If

End Sub
If I want to get a one-off sum of something and use it in another program, this comes in handy. I could SUM in a cell, copy that
cell, paste it, and delete it. If I paste into Notepad, its fine, but if I try to paste into Outlook or even Gmail those programs try to
get fancy and make an HTML table. Sometimes I just want the text.
One shortcoming of this procedure is that it doesnt do well with filtered cells. The Selection includes both visible and hidden cells,
but I probably only want visible. Im changing the code to
doClip.SetText Application.WorksheetFunction.Subtotal(9, Selection)
so it works with filtered data.
Category: Copy and Paste, Keyboard | 7 Comments
Where to Find Data
April 29, 2014, 6:30 am by Dick Kusleika
Of course I use my sample data generator when I need some sample data. But sometimes I want some real data. I looked high
and low for data sources to include in the upcoming 101 Ready to Use Excel Formulas book that Mike and I are writing. If you like
data as much as I do, there might be a few sources you havent found on my pinboard page.
https://pinboard.in/u:dkusleika/t:data/
If you have a good one thats not on that page, leave it in the comments.
Category: Data Analysis | 5 Comments
Printing Labels on a Dymo LabelWriter 450 from VBA
April 28, 2014, 9:18 am by Dick Kusleika
Hows that title for Google-ability. Pretty saucy, Id say. Heres an affiliate link if youre in the market for one of these label
printers.
LabelWriter 450
Back in 2010, I was printing labels on a Dymo from VBA. At my current job, I had occasion to do it again, so I bought a LabelWriter
450 from Amazon. Seventy-five bucks! What a deal.
Previously I didnt need anything fancy formatting-wise. I could just push some text at a DymoLabels object and print it. Im not so
lucky this time around. I really needed some underlines for visual separation of data. I dont see any way to underline stuff through
the Dymo object model. But what I did discover was that the .label files created by their software are just XML files. Woot!
Rather than trying to navigate a klunky object model, I can just write to a text file. Heres what the new labels look like.
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 3/9
And heres a piece of the XML file.
<Element>
<String>Int BOL Ext BOL Gallons Price Total
</String>
<Attributes>
<Font Family="Courier New" Size="10" Bold="True" Italic="False" Underline="True" Strikeout="False" />
<ForeColor Alpha="255" Red="0" Green="0" Blue="0" />
</Attributes>
</Element>
<Element>
<String> 22753 6,418 2.9775 19,109.60
18318 24094018 830 3.3361 2,768.93
18318 0 </String>
<Attributes>
<Font Family="Courier New" Size="10" Bold="True" Italic="False" Underline="False" Strikeout="False" />
<ForeColor Alpha="255" Red="0" Green="0" Blue="0" />
</Attributes>
</Element>
The XML isnt terribly pretty mostly because there are line feeds in there. Without the line feeds, I think it would be indented
properly. Each Element tag has a String tag and an Attributes tag. It looks like every font attribute is listed whether you
specifically set it or not. Im also padding my text with spaces to line up columns. I could use multiple text boxes, but there is no
grid control. For now, this works. The only downside to using one big textbox and space padding is that I have to use a fixed-width
font Courier New in this case. If I want to use a nicer font, Ill have to go the multiple textbox route.
I have this form for data input and a button to print the label. The button kicks off the code below. I dont need the mdyLabel
variable any more because Im not using that part of the object model. Instead of mdyLabel, Im manipulating the XML file directly
giving me more control.
Sub PrintBlendCalc()
Dim vaPrinters As Variant
Dim i As Long
Dim sFile As String

Const sMSGNODYMO As String = "Dymo label printer not found."

If mdyAddin Is Nothing Then
CreateDymoObjects
End If

If Not mdyAddin Is Nothing Then
vaPrinters = Split(mdyAddin.GetDymoPrinters, "|")
For i = LBound(vaPrinters) To UBound(vaPrinters)
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 4/9
If mdyAddin.IsPrinterOnline(vaPrinters(i)) Then
mdyAddin.SelectPrinter vaPrinters(i)
Exit For
End If
Next i

UpdateLabelFile sFile
mdyAddin.Open sFile
mdyAddin.Print2 1, True, 1
Else
MsgBox sMSGNODYMO, vbOKOnly
End If
End Sub
Instead of using the SetField method (like in the previous example), I call a new procedure called UpdateLabel file to create a new
XML file. Then I open the file and print it.
Public Sub UpdateLabelFile(ByRef sFile As String)

Dim xDoc As MSXML2.DOMDocument
Dim xStrings As MSXML2.IXMLDOMSelection
Dim vaData As Variant

'Get the label data in an array
vaData = wshBlendCalc.Range("B2").Resize(7, 5).Value

'Create a new XML Doc and load the template label
Set xDoc = New MSXML2.DOMDocument
xDoc.Load msLABELPATH & "BlendCalc.label"

'Get all the "String" elements (there are 4)
Set xStrings = xDoc.getElementsByTagName("String")

'Change the text of the four string elements
xStrings(0).Text = FormatLabelText(vaData, 1)
xStrings(1).Text = FormatLabelText(vaData, 2) & FormatLabelText(vaData, 3)
xStrings(2).Text = FormatLabelText(vaData, 4)
xStrings(3).Text = FormatLabelText(vaData, 5) & FormatLabelText(vaData, 6) & FormatLabelText(vaData, 7)

'Save the XML file
sFile = msLABELPATH & "NewOrders\" & vaData(2, 2) & "_blend.label"
xDoc.Save sFile

'Save the data to a text file for those people who don't read XML that well
Open msLABELPATH & "NewOrders\" & vaData(2, 2) & "_blend.txt" For Output As #1
Print #1, FormatLabelText(vaData, 1) & _
FormatLabelText(vaData, 2) & _
FormatLabelText(vaData, 3) & _
FormatLabelText(vaData, 4) & _
FormatLabelText(vaData, 5) & _
FormatLabelText(vaData, 6) & _
FormatLabelText(vaData, 7)
Close #1

End Sub
There are four elements in my XML file. The first label line is underlined, so that gets its own element. The second and third lines
and a portion of the fourth line have the same attributes, so theyre grouped into one element. The portion of the fourth line that
is underlined is in the third element. And all the rest of the text goes into the fourth element. The elements are set and the
attributes are just the way I want them, so all that is left is to update the text.
I pass the array into a FormatLabelText function which extracts the data I want and pads the spaces so the columns line up. The
FormatLabelText function is shown below.
I pass the sFile variable ByRef into UpdateLabelFile. The sFile variable is set and retains that value back in the calling procedure
so the calling procedure knows which file to open and print.
The FormatLabelText function takes the array and whichever row were interested in formatting. It starts by defining three arrays:
vaBuffer defines how much padding for each of the five columns; vaAlignLeft defines if the columns are aligned right or left; and
vaFormat defines the number format for each of the five column (@ is the format for general text).
Public Function FormatLabelText(ByRef vaData As Variant, ByVal lIndex As Long) As String

Dim sReturn As String
Dim vaBuffer As Variant
Dim vaAlignLeft As Variant
Dim vaFormat As Variant
Dim sData As String
Dim j As Long

vaBuffer = Array(9, 11, 11, 8, 10)
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 5/9
vaAlignLeft = Array(True, True, False, False, False)
vaFormat = Array("@", "@", "#,##0", "0.0000", "###,##0.00")

For j = LBound(vaData, 2) To UBound(vaData, 2)
sData = Format(vaData(lIndex, j), vaFormat(j - 1))
If Len(sData) = 0 Then
sData = Space(vaBuffer(j - 1))
ElseIf Len(sData) > vaBuffer(j - 1) Then
sData = Left$(sData, vaBuffer(j - 1) - 1) & Chr$(133)
ElseIf Len(sData) < vaBuffer(j - 1) Then
If vaAlignLeft(j - 1) Then
sData = sData & Space(vaBuffer(j - 1) - Len(sData))
Else
sData = Space(vaBuffer(j - 1) - Len(sData)) & sData
End If
End If
sReturn = sReturn & sData
Next j

FormatLabelText = sReturn & vbNewLine

End Function
First the data is formatted using the Format function and the vaFormat array. Next, the big If..ElseIf..EndIf block determines how
to pad the data with spaces.
If the data is empty (Len = 0) then write spaces for the whole buffer.
If the data length is greater than the buffer, truncate it and add an ellipse to the end.
If the data length is less than the buffer, add spaces to the end (or the beginning if its aligned right) to fill it out.
It would be nice (but hard) to create a more general purpose function that created a label from a range. But this works for now.
Category: VBA | 6 Comments
KwikOpen Addin
April 25, 2014, 6:30 am by Dick Kusleika
Ive been using this recent files userform for quite a while now and I like it. I havent added Erics comment yet (and for no good
reason), but Im going to in the next version. I dont know if that solves the Sharepoint problem or just the ChDrive problem as
neither are problems for me.
Here are my two problems:
Not enough recent files. Im shocked SHOCKED at how often 50 recent files is not enough. Its usually when I have to open a
whole bunch of very similar files that I will never open again, but that clean out my recent files list. I decided to, sort of, maintain
my own list. Because I use class modules *ahem* changing things to maintain my own list was pretty easy. I had to change how I
fill the CRcntFiles class, but everything that consumes that class downstream just works. Heres the new Fill method in CRnctFiles.
Public Sub Fill()

Dim rf As RecentFile
Dim clsRcntFile As CRcntFile
Dim sFile As String, lFile As Long
Dim vaFiles As Variant
Dim i As Long

For Each rf In Application.RecentFiles
Set clsRcntFile = New CRcntFile
clsRcntFile.FullName = rf.Path
Me.Add clsRcntFile
Next rf

sFile = ThisWorkbook.Path & Application.PathSeparator & msMRUFILE
lFile = FreeFile
Open sFile For Input As lFile

vaFiles = Split(Input$(LOF(lFile), lFile), vbNewLine)

Close lFile

For i = LBound(vaFiles) To UBound(vaFiles)
If Len(vaFiles(i)) > 0 Then
Set clsRcntFile = Nothing
Set clsRcntFile = Me.RcntFileByFullName(vaFiles(i))

If clsRcntFile Is Nothing Then
Set clsRcntFile = New CRcntFile
clsRcntFile.FullName = vaFiles(i)
Me.Add clsRcntFile
End If
End If
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 6/9
Next i

End Sub
First, I read in the 50 Excel most recently used files. Then I read in the 1,000 most recently used files that I store in a text file,
weeding out the duplicates as I go. The advantage of continuing to use the Excel MRU is that I can leverage its pinning feature. I
dont have to write my own pinning bullshit if you want to pin something, do it via Excel and it will always be in the MRU.
Awesome.
Why 1,000 files? I dont know. Well see how the performance holds up. Ive been using it for three days and my text file is only up
to 58 files the 50 Excel stores plus eight additional. I guess it will take a bit longer to get to 1,000 than I thought, but I think it
will be clear when their are too many and I can pare it down.
Next I need a way to write the files back to the text file. When the userform closes, the CRcntFiles.WriteToDisk method is called.
Public Sub WriteToDisk()

Dim sFile As String
Dim lFile As Long
Dim clsRcntFile As CRcntFile
Dim aFiles(1 To 1000) As String
Dim lCnt As Long

lCnt = 0
For Each clsRcntFile In Me
lCnt = lCnt + 1
If lCnt > UBound(aFiles) Then Exit For
aFiles(lCnt) = clsRcntFile.FullName
Next clsRcntFile

sFile = ThisWorkbook.Path & Application.PathSeparator & msMRUFILE
lFile = FreeFile

Open sFile For Output As lFile
Print #lFile, Join(aFiles, vbNewLine)
Close lFile

End Sub
I lazily write 1,000 lines to the disk even if I dont have that many. I mean efficiently, not lazily. The text file is 6KB, so Im not
losing sleep over it. I would be pretty trivial to Redim Preserve that after Ive filled it up, so I supposed Ill do that after the alpha
test.
And other than a few minor tweaks, thats the only changes I had to make. If thats not a case for using class modules, I dont
know what is. My userform consumes a CRcntFiles class. It doesnt care how that class gets filled up or where the list comes from.
I could change to storing those recent files in the registry, in an XML file, or tattooed to my back. As long as I can get them into a
CRcntFiles instance, the rest of the code is happy.
Save As is jealous of Open. My next problem is that while I can quickly open a recent file, I cant quickly save a file to a recent
place. This is primarily a problem when I open attachments in Outlook. It stores an opened attachment in the Temp folder and
when I choose Save As, thats the folder it starts me in. Nuts to that. If you download this add-in, youll also see that Ive hooked
up a SaveAs userform to Ctrl+Shift+S. Its got a few problems too (it prompts to replace a file twice), but you can try it if you like.
You can download KwikOpen.zip
Category: File Operations, Userforms and Controls | 3 Comments
The Great Hungarian Debate
April 23, 2014, 6:30 am by Dick Kusleika
Ive discussed this in 2005. Then again in 2009. I guess its time to revisit the issue, mostly because Jordan says its time to say
goodbye to hungarian notation.
Ive probably said everything I need to on the subject, so no long diatribes here. However, I decided that I was going to
experiment with coding without Hungarian and see what I thought. A little experimentation cant be bad. I have a choice. I can be
stubborn and not learn anything or I can force myself to try something different and maybe Ill be the better for it. There was a
time when I never coded custom class modules. Now you cant get me to shut about them.
Here is the first procedure I coded in my experiment:
Public Sub ReformatDrivers()

Dim Cell As Range
Dim Found As Range

For Each Cell In Sheet1.Range("A2:A133").Cells
Set Found = Sheet2.ListObjects(1).DataBodyRange.Find(Cell.Value, , xlValues, xlWhole)
If Not Found Is Nothing Then
Cell.Offset(0, 1).Value = Sheet2.Cells(Found.Row, 2).Value
Cell.Offset(0, 2).Value = "'" & Sheet2.Cells(Found.Row, 1).Value
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 7/9
Cell.Offset(0, 3).Value = Found.Offset(0, 1).Value
End If
Next Cell

End Sub
Not exactly a barn burner, Im sure youll agree. I hated every minute of it. I hate reading it right now. Ive struggled to pinpoint
why it displeases me so, but I have a theory.
Its hard to tell the difference between keywords and variables. For Each Cell are all one syllable words with the first letter
capitalized. The color distinction actually shows up better on this blog than it does in the IDE. I could change my color options in
VBA so it stands out a little better.
Theres no requirement to make my variables proper case and thus hard to distinguish. I could code For Each cell and make my
variables stand out because theyre lower case. But there is a substantial advantage to using capital letters the IDE fixes your
caps and tells you if you have a typo. So I want to have at least one capital letter to get that benefit. I could use camel case for
two syllable words, like fileName. Do I have to always avoid one syllable words?
As Ive mentioned in the past, I dont use data type prefixes in other languages. But like this experiment, I dont really like the
variables I use when I code Ruby and I think its for the same reason. The difference is that my Ruby IDE doesnt fix caps and,
maybe more importantly, everything about Ruby is new and novel and foreign so on the scale of strangeness, all lower-case
variables dont really rate.
Another advantage of data type prefixing is being able to use reserved words. For my experiments, if I want to use a reserve word
Im going to tack on an underscore. When I want to code Dim lEnd As Long, I will instead use Dim End_ As Long.
I havent made a userform yet, but there is a problem that Im not sure how to solve. Most of my controls have labels and any
control with a label is named the same as the label. The textbox tbxSearch has lblSearch. The combobox cbxCustomer has
lblCustomer. Theres real value in that and Im not sure how to get away from it. Another problem with userforms are class
properties. When I start typing Me.tbx I know Im getting a textbox. But if my textbox is called CustomerName and I have a
property of the userform class to hold a customer name, how do I distinguish them without the tbx? Thats not a rhetorical
question, I really want to know how people do it.
Ill keep writing new code without data type prefixing until I cant take it anymore. And, of course, Ill keep bitching about right
here.
Category: VBA | 11 Comments
The Error Class Revisited
April 21, 2014, 6:30 am by Dick Kusleika
In the comments to Error Handling Via an Error Class, Peter found that the problem with this method is the absence of the Stop
and Resume in the error handler than let you debug at the line that caused the error. Yeah, that stinks. Then Jase got me thinking
that I just wouldnt create the class in debug mode. Well, that wasnt quite right. What needed to happen was that the error
handler should not be set in debug mode. Heres a rewrite of the entry point procedure.
Sub EntryPoint()

Dim clsError As CError

gbDebugMode = False

If Not gbDebugMode Then On Error GoTo ErrHandler

Set clsError = New CError: clsError.SetLoc "Module1", "EntryPoint"

SubProc1

ErrExit:
Exit Sub

ErrHandler:
Set clsError = Nothing
MsgBox Err.Description
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 8/9
Resume ErrExit

End Sub
When gbDebugMode is False, the error handler is set and it works as described in the original post. That is, the user gets a
message box and the code exits gracefully. When gbDebugMode is True, the error handler is not set. Its like you dont have an
error handler at all because you dont. When in debug mode, you get kicked to the line that caused the error.
Is that that last hurdle?
Category: Classes, Events | 3 Comments
Back to Blogging
April 19, 2014, 5:51 pm by Dick Kusleika
I just submitted the last chapter of a super-awesome new book project Im doing with Mike Alexander. Submitting the last chapter
is always a great feeling. I have no idea when it will be available, but Ill be pimping it right here when I know. Its a formulas
book, and did I mention that its super-awesome?
Last month was the 10 year anniversary of DDoE. Wow, ten years feels like a long time. The only way to see the first post from
March 2004 is in the wayback machine. It was lost in the great data loss event of a couple years ago. I had designs to restore all
the lost posts, but it has not happened. I still have hope that will happen.
That first post was about summing between two dates. It was the old trick where you sum less than the greater date and subtract
the sum of less than the lesser date. Now that Excel has SUMIFS, that trick is obsolete. That may be why Im not so eager to get it
back online.
Did you know that DDoE was originally at dicks-blog.com? John Walkenbach convinced me to start a blog during a trip to Seattle
back in the day. We came up with the URL at the bar. I think he was trying to make hyphens more socially acceptable in URLs. The
early aughts were a strange time.
If you follow DDoE, you know weve had some trouble here of late. Something has been spiking the memory and shutting down
MySQL. It hasnt happened in a while, but that may be because there hasnt been much activity. Hopefully all thats behind us.
Thanks to Jeff Weir and the other contributors for all the posts theyve made.
Ive got several posts queued up (including one on keyboard shortcuts if you can believe that) so stay tuned for those and an
announcement on when the new book will be hitting the shelves.
Category: Uncategorized | 1 Comment
A VBA performance class
April 18, 2014, 12:33 pm by jkpieterse
Hi everyone!
If you write a lot of VBA code you probably sometimes run into performance issues. A customer rings you and complains that the
Excel file you built for them does not perform well. Ive written a small article on my site, inspired by a post here: Error Handling
via an Error Class. I needed a quick way to log and report performance of subroutines and I also wanted to see how many times a
routine was called.
See: A VBA performance class
Enjoy!
Jan Karel Pieterse
www.jkp-ads.com
Category: Automation, Classes, Excel Advanced, MVP, Performance, VBA, VBA Advanced | Comment
Paste and Transpose icon in QAT crash Excel 2013
April 12, 2014, 12:26 pm by Ron de Bruin
Hi all
I add a new page on my site with a workaround for this problem. I hope that there are no more of this problem icons for the QAT.
Not easy find the problem with bugs like this, you not think that an Excel icon in the QAT can crash Excel.
5/1/2014 Daily Dose of Excel
http://dailydoseofexcel.com/ 9/9
Paste and Transpose icon in QAT crash Excel 2013
http://www.rondebruin.nl/win/s2/win018.htm
Regards Ron de Bruin
http://www.rondebruin.nl/
Category: Excel 2013 | Comment

Potrebbero piacerti anche