Author Archives: markn

About markn

Mark is the owner and founder of Timesheets MTS Software, an mISV that develops and markets employee timesheet and time clock software. He's also a mechanical engineer, father of four, and a lifelong lover of gadgets.

    Find more about me on:
  • googleplus
  • linkedin

DatePickers on Excel MultiPage Controls

I’ve known this for a little while but I thought it worth posting here. You cannot get or assign the value of a DatePicker control on a MultiPage control if you’re on a different page of the MultiPage control. So if you’ve got a 5 page MultiPage control and the DatePicker Control is on page 1 of the MultiPage then this won’t work (and will indeed give an error):

  Me.MultiPage1.Value=4
'dtPicker is on MultiPage1 page 1, 
  Me.dtPicker.value=Now

And this wont work either:

  Dim datTmp as Date
  Me.MultiPage1.Value=4
'dtPicker is on MultiPage1 page 1, 
  datTmp=Me.dtPicker.value
 'this just sets datTmp to todays date and ignores the actual dtPicker value

So if you want to set or get the value of a DatePicker on a MultiPage control you need to be careful which page of the MultiPage is selected. You need to do something like this.

 'save the page we are on now
  iCurrentPage = Me.MultiPage1.Value
  
  'change to the page the DatePicker is on and set the value
  Me.MultiPage1.Value = 4
  Me.dtPicker.Value = Now
  'go back to the original page
  Me.MultiPage1.Value = iCurrentPage

The Customer is Always Right (Sometimes)

The old adage is that the customer is always right. This isn’t true, not by a long shot. You need to know right now that your software users will be, on the whole, selfish and only interested in scratching their own itch. They don’t care if your software product is designed specifically for them and unsaleable to anyone else. They don’t care if their email is the only one you answer today. And they don’t care if you go broke, just as long as you keep giving them the service they demand. I’m telling you now, if you do assume the customer is always right you are heading into dangerous waters and there be dragons in those waters.

Don’t Change Your Software Based on What Customers Want Until…

Here’s a curly one. I am saying to you now, do not change your software product based on what your customers ask for. Up until a point. And that point is where you have been asked for the same thing, so many times by so many customers that it is the first thing you think about when you sit down to do some development work. Stay true to the vision of your product UNTIL the consensus from your user base is such that it can no longer be ignored.

I apply this rule almost fanatically these days. You see, when I got started in the software selling business I thought that I had to be all things to all men. As a consequence my first product grew new features like crazy and I had a bunch of happy customers who had customized software for basically chicken feed. And the end result of this after a couple of years was a product that tried to be all things to all men and ended up being ideally suited to no-one. I don’t even want to talk about what a nightmare that code-base ended up being to support. Continually being reactive to my customer demands caused me to lose track of my initial vision for the product lead to complexity that even I, as the author of the software failed to really comprehend.

The Squeaky Wheel Shouldn’t Get the Grease

Prepare yourself for something. If you’re going solo and planning on providing technical support you’re going to get rude customers. Not just rude paying customers but people who think they deserve to get your hard work for free and others who feel the need to critique your work in rather abrupt language. Don’t get upset by this. Don’t get reactive to it. And certainly, never, ever, make a special effort to appease such characters.

It’ll be hard because when you get a rude email because you’ll see red and want to bang out a reply defending your products (which are your babies after all), and perhaps you’ll want to engage them in debate. Don’t. You can never win. If a rude customer asks for a refund, give them one and reply with the same canned response you would use if a polite customer asked for one. If a rude customer flies off the handle at the way your software does something, respond politely using the same words you would to a civil customer. And if a customer sends an email that just makes you plain angry get up, and walk away. Email is great like that, you can just get up and do something else.
If you take these simple steps I can assure you that in most cases the customer will calm themselves down. We can never know what is going on in a person’s head when they send out poison via email and it’s remarkable how many of them realise what asses they’ve been when their emails are replied to a civil, polite and professional fashion.

Don’t Be Scared to Fire Your Users

Some users are just high maintenance. They take up your time with technical support during your software trial period, they clearly do not read the help file, or your blog, or your myriad of other technical resources. What’s even more frustrating is that they don’t even seem to read the emails you so carefully craft in response to their questions. Treat each of these high maintenance users like gold because if you can, finally, get them to understand your software they’ll become loyal devotees. I’ve had users like these that have maintained a dialog with me for years, which sounds like hard work but each year they happily pay their annual support fees. Which makes me happy too.

Sometimes though, the high maintenance users cannot be saved. You need to recognise these users during your software trial period and fire them before they can spend money on your software. If you can’t save them during the trial period you’re almost certainly not going to save them afterward and once money has changed hands these high maintenance users can get nasty. I used to close sales with all high maintenance users but too many times this lead to disputes and eventual refunds. So these days I quietly fire the users before they purchase and most of the time they don’t even realise I’ve done it. I do it by sending them this email:

Dear Joe Smith,
Before you purchase XXXXX I strongly recommend that you run the product for the full 30 day trial period. Furthermore to make sure that XXXX is a great match for your company I’ve decided to extend the trial period by a further 60 days! Just register the software with the registration codes below and you’ll be able to use XXXX for free for 90 days!
///registration codes here////

This has worked beautifully many times. The user hands over no money and when they give up trying to use your product (which they usually will) you’ll never hear from them again. A potential side benefit to this approach is that your user may actually get a eureka moment during their extended trial period, figure it all out, and buy the software. It’s a win-win situation whatever happens.

How Just Being Nice Can Work

It’s been quiet here lately. My online businesses have been taking up all of my time as have a number of different new projects my partner and I have been working on. I thought it was worth popping in to share small story though.

I’ve been concentrating on providing all of my customers with an exemplary support experience in the last 4 months. That’s not to say I haven’t always wanted to give them best support I can, but it’s something I’ve really been working hard at lately. Just small things like addressing each email personally to them, sending a follow up if I haven’t heard back from them, and making sure to thank them when they let me know if a problem has been solved. This means I spend a bit longer on my support tasks but hopefully it results in a more engaged customer base. More likely to persist with using my products, more likely to pay their support renewal when it comes due, and more likely to mention my products to others in real life.

The last couple of days saw one user of Timesheets Lite think she was using the free version when in reality she’d been using the trial of the commercial version. She wanted to keep using the software for free. This does happen from time to time (perhaps 2-3 times a year) and usually adopt a no-compromise stance something along the lines of “buy the software if you want to keep using it”. They’ve run the trial through 30 days with continual warnings that the software WASN’T the free version and only decided to do something about it when they are finally proven it really isn’t the free version when the trial expires and they are locked out.

In this case I decided to take a different approach more along my current “exemplary customer service” track. I offered to give the user a free Timesheets Lite license if she would write a short paragraph on how she’s using the software and what sort of benefits she’s seen from using it. To my surprise she responded quickly and said “That is a perfect compromise and I really appreciate it. Customer service is everything!”. And bought a license. So there you have it. Be nice, don’t take the hard line, and you may just end up winning a customer you were never going to win any other way.

PHP and Dates – Tearing My Hair Out

I had an interesting problem this morning with some dates in PHP. When I use dates in PHP I generally try to handle them as a unix timestamp using the local unix time of the server. I then modify this based on clients timezone to show them their local time. This has worked fine up until now.

November the 4th 2012 was the day that daylight savings rolled back in the USA and this caused a problem when reports for one of my products were run across this transition day. The trouble was when you got a local server time and converted it to a client time. For example using something like this:

$date=mktime(8,0,0,11,4,2012); //set to 8 AM on November 4
$date_time=new DateTime("now",new DateTimeZone('America/Los_Angeles'));
$date_time->setTimestamp($date);
echo "date_time:: ".$date_time->format("D j m y h:i:s");

Resulted in a different time to:

$date=mktime(8,0,0,11,5,2012); //set to 8 AM on November 5
$date_time=new DateTime("now",new DateTimeZone('America/Los_Angeles'));
$date_time->setTimestamp($date);
echo "date_time:: ".$date_time->format("D j m y h:i:s");

Which normally isn’t a problem except when you’re cycling through a date range one day at a time by adding (24*60*60) seconds to each day and expecting the client time to be indexed one day at a time too. But, it’s not, on one of the days there’s going to be an extra hour (or an hour) less. So, the solution (and it’s horrid) is to convert server to time to local client time and add a day to that, and then convert it back to server time. Yuck. But it works, and it works something like this:

	//
	//convert to local time
	//		
	$start_date=mktime(8,0,0,11,1,2012);
	$date_time=new DateTime_52("now",new DateTimeZone('America/Los_Angeles'));
	$date_time->setTimestamp($start_date);
			
	for ($i=0;$i<7;$i++)	
	{
		$date_time->setDate($date_time->format("Y"),$date_time->format("m"),$date_time->format("j")+$i);	
		echo "day ".$i." local time ".$date_time->format("D j m y H:i:s")."<br />";
		echo "day ".$i." server time ".date("D j m y h:i:s",$date_time->getTimestamp())."<br />";
	  $first_day_of_week1=get_first_day_of_week($date_time->getTimestamp(),new DateTimeZone('America/Los_Angeles'));
		echo "day ".$i." first_day_of_week:: ".date("D j m y h:i:s",$first_day_of_week1)."<br />";
		
	}

Google Experiments

Google Experiments

Google Experiments

I use Google Analytics to monitor the traffic on my websites. Have done since it was Urchin and Google bought them up. There’s a pretty neat feature in there called Google Experiments which allows you to perform AB tests on different web layouts pretty simply. Above you can see a test I’m running at the moment comparing two very different layouts of a page on my website. Setting up the experiment was very easy. Here’s the steps I followed:

  1. Designed the new layout and uploaded it and make sure it worked OK.
  2. Setup the new experiment in my Analytics account.
  3. Uploaded some tracking javascript into the header of the HTML file for the new layout and old layout.
  4. Decide how much traffic to divert to the experiment. In my case I chose 100% because I was confident the new layout would be at least as good as the old one. If you’re trying something radical I guess you’d direct less traffic to the experiment just in case something bad happens.
  5. Start the experiment and monitor your stats. Google decides when the experiment is over and assigns a winner or a loser or decides it cannot split the difference.

It helps if you’ve got some Goals setup for your Analytics account so you’ve got something to measure the experiment by. Don’t forget to look at other things though, such as the time visitors spend on your site and the bounce rate. Right now my new layout is outperforming the old layout by 13% and has outperformed it on 7 of 11 days the experiment has been running. 13% doesnt sound like much but it works out to about 700 extra conversions a year. Not too shabby.

If you want some more information I’d suggest taking a look at the Google Analytics Experiments help page.

Google Antics

Everyone knows about Google and nearly everyone uses it to do their searches. It’s become so dominant in the market that small online businesses (like mine) can be made or broken by where they appear in Google searches. Appear in the first 10 SERPs (Search Engine Ranking Positions) and you can make some money. Appear in the first 5 and you could make good money, appear as number 1 and you could potentially make LOTS of money. So getting high up in the Google rankings for your product search terms is important, and as with anything important that money can be made from there’s a whole industry formed around getting high Google rankings. It’s known as the SEO (Search Engine Optimisation) market. And it’s shocking.

People charge huge money to optimise a site and VERY VERY few have any concrete idea about what they are doing and the effects it might have on Google rankings in either the long or short term. The main reason for this is that Google hold their cards very close to their chest, and while they might give general indications of the things that affect search engine rankings they never, ever provide intimate details. The reason of course is that they do not want people gaming the rankings for financial gain. Not that this actually stops anyone, because hundreds of thousands of web-sites are spawned every year just to game the rankings and make their owners a few quick bucks.

Back in the day (more than 5 years ago) I used to read various SEO blogs and forums. But gradually I realised that no one person really knew what they were talking about and constant Google algorithm updates were constantly shifting the goal posts of the SEO game. That’s the key problem you see, Google changes their algorithm that ranks web-sites in searches ALL THE TIME. And whenever an update happened there’d be an up-roar about this site that gained rankings and that site that dropped and much wailing and wringing of hands by web-masters whose gaming of Google suddenly didn’t work any more. So I quit reading SEO blogs, I quit reading SEO forums, and I unsubscribed from all my SEO mailing lists. And I just concentrated on building better products and adding useful content to my web-sites.

The only slightly SEO based activity I’ve taken part in for years is making sure that I research the right keywords for my products, make sure those keywords are in page <h1> tags and that the keywords appear a few times in my text. That’s it. No link building, no auto content generation, no paying SEO consultants, no mini-sites, no nothing. And Google has (apparently) rolled out dozens of updates in that time and I couldn’t have cared less. Links to my web-sites have grown naturally, reviews of my products have popped up, and I’ve had mentions on social media sites, all without me getting involved. And my life has been better for it.

Until mid-October 2012 that is. That’s when I noticed that traffic to one of my major sites was down a bit, maybe 15%. Which is unusual because my web-traffic follows a pretty predictable pattern and has done for 5 years. Anyway it turned out that at the end of September Google announced they’d be rolling out an update that devalued exact match domains. Exact match domains use keywords in their domain names to try to get a bonus in their Google rankings. So, if I was selling blue foozles, I’d try to register an exact match domain like www.blue-foozles.com anticipating that Google would rank me higher because of it. All in all this isn’t a bad thing but of course if there’s money to be made the low-lifes crawl out of the gutter and hey-presto the internet became inundated with spammy exact match domain web-sites. So it turns out in late September 2012 Google said “no more” and appears to have removed the bonus that exact match domains (and apparently partial match domains) gained.

And that’s what zapped my traffic. Almost all my software product domains are partial match domains. That’s because I’m particularly unimaginative when it comes to naming my products. If it’s a timesheet program then I call it timesheet something-or-other. If it’s a time clock program then I’m going to call it time-clock-a-ma-jig. If it’s a coin collecting application then I’ll call it coin-collector-whatsit. Now I am not the first person to do this, there’s a little WORD processing program you may have heard about called Microsoft WORD, and a book-keeping program called QuickBOOKs, and a little known anti-virus program called Norton ANTI-VIRUS. So in these cases (and mine) the keyword is the BRAND. And sadly it appears that right now I might be getting walloped in the search engine rankings because of my brand.

New Laptop in Da House

I think I’ve bought 10 different Dell laptops in the last 8 years or so. They’ve all done their jobs admirably apart from one memorable XPS laptop which can only be charitably described as a piece of poo. That laptop gave me nothing but troubles from day one and despite Dell’s best efforts (and 4 or 5 on-site visits from a tech) could never be made to work correctly. To Dell’s credit they gave me an exchange computer to replace that computer and the replacement (a Vostro 14″ machine) has been flawless.

Anyway, my partner has been using a 15.5″ consumer grade Inspiron with Windows Vista for the last 4 years and it was starting to have some problems. I hate fiddling with computers to fix up glitches, especially 4 year old computers that are well past their use-by date. So rather than fix that PC off to the Dell Australia Outlet Store I went. I’ve had some luck picking up cheap machines and monitors from there in the past so I thought I’d try my luck again. The only criteria for the new machine were that it be a laptop, that it have Windows 7×64, and it have 8GB of RAM. There we a couple of likely prospects, one of which was an Inspiron and the other was a Vostro 3560. Ten minutes on the phone to Dell told me that the Inspiron wasn’t available any longer but the Vostro was and the purchase was made. 5 days later the new machine landed on our front doorstep.

The Dell Vostro 3560 seems like a nicely built machine. It’s certainly much nicer to handle and look at than the old Inspiron clunker it replaced. 4 hours of fluffing about with it last night as I moved the data from the old machine to the new one showed no problems at all with performance being snappy. Hardware wise the USB ports are a trifle stiff to get plugs into but the monitor is excellent with a 1920×1080 resolution. Even with a titchy 15.5″ monitor everything was quite readable at this resolution.

Of course this is no long term test but after 12 hours in our life the Dell Vostro 3560 laptop has done what it’s supposed to do perfectly. Recommended.

Munin and Disk Space

This entry is really here to remind me what went wrong with Munin so the next time it happens I am likely to remember. I use Munin on my web servers to monitor them. I run Munin nodes on the web-servers and the Munin master is another computer that just serves up the Munin web pages and runs some rsync commands via cron jobs. This system has been working faultlessly for 2 years and then on September 26 2012 it stopped updating the graphs. Yesterday I finally got around to figuring out why it didn’t work any longer.

First thing I did was take a look at the munin logs on the clients, these are in the /var/log/munin directory. These logs were showing a last modified date of September 26, the same date the munin graphs stopped updating. I opened up the last log in nano and there was exactly nothing of help in there. So I tried re-starting the munin node process with:

restart munin-node

I sat there watching the log files for 5 minutes hoping they’d update. Sadly they didn’t. So I started up a new PuTTY session with the machine running the munin master took a look at the munin logs in /var/log/munin/. They all had the September 26 modified date too. I had a quick look through the logs and couldn’t see anything in there either. Next step was to force a manual update of the munin master and see what happened there. I did this by changing to the munin user with:

su - munin --shell=/bin/bash

And then running the munin-update (which gets all the data from the munin-clients)

/usr/share/munin/munin-update --debug

When I ran this command the update, which should be hundreds of steps was just four steps with the last one complaining about there being no free disk space! Eureka!

Next step was to check the disk usage on the server. I sorted this by directory and displayed it in human readable format with:

du -sh * | sort

This indicated that a directory that contained database backups was using up almost all the disk space on the server. A quick removal of older files from this location freed up a lot of space. I forced a munin update again and hey presto everything started working.

All of this would have been easily solved if I actually had munin monitoring the server that acts as my munin master, but of I course I haven’t done that. Stupid me. I’ll put that on the to-do-list, but for now at least the problem is solved and will not re-occur for several months.

IE9, radio buttons and DIVs

I’m just getting back into some development of Online Time Clock MTS and had the pleasure of squashing an annoying bug today that was only appearing on IE9. I used the prototype javascript library pretty heavily in the development of this online system and getting the value of a group of radio buttons is something of a pain but can be done like this:

var selected_value = Form.getInputs('form_name','radio','radio_group_name').find(function(radio) { return radio.checked; }).value;

This returns the value of the selected radio button of the group you’re interested in. Works perfectly until you go and put a <DIV> </DIV> in the middle of your HTML radio buttons. Then IE9 decides that the radio buttons AFTER the div are no longer part of the radio group. The above javascript will then throw an exception if one of the radio buttons after the offending DIV is selected. The simple fix (for me at least) was to change the <DIV> to a <SPAN>

Fun With Gate Remotes

Broken Remote

Broken Remote

Don’t mess with me if you are a remote. Above are the broken remnants of a Gliderol TM-305C remote control that never worked properly. One day it chose to not work properly at the wrong time and as a result got smashed to bits by myself. Temper, temper. After calming down I bought another remote off of eBay thinking it wasn’t too much of a hassle because programming the remote to run our garage door is a doddle. Little did I think about how to program the remote to work our front gate. After some internet searches (useless) and poking about inside the gate actuator I figured out how to program the remote so I thought I would post it up here so I have a reminder of how to do it the next time I take out my frustrations on the remote control.

Deimos Gate Actuator

Deimos Gate Actuator

Above you can see the Deimos BT gate actuator that moves the gear rack attached to the bottom of our sliding gate. The actuator cover is held on by two stainless screws which when removed allow you to see the innards of the actuator as shown below.

Deimos Gate Actuator Innards

Deimos Gate Actuator Innards

The actuator looks pretty neat, at the top left you can see two 12V batteries so we can open the gate when the power is off. The grey box at the front contains the actuator controller and just peeking around the top right is a fashionable looking beige box that contains the receiver for the Gliderol remotes. I worked this out because someone had helpfully labelled the box “1814 G/Matic Receiver Stand Along”. “G/Matic” presumably stands for Glidermatic which is Gliderol’s name of choice for anything electrical or electronic.

Glidermatic Receiver Box

Glidermatic Receiver Box

Removing the natty beige cover was done by unscrewing four screws and hey presto we are in circuit board land.

Receiver Circuit Board

Receiver Circuit Board

Now this circuit board looked pretty identical to the receiver board in our Gliderol garage door opener (you can see the Gliderol Remote Training Instructions here). Given it’s similarity I used the same technique to program the remote. I pressed the button on the circuit board (indicated by the arrow labelled A) which made the LED on the board (labelled helpfully as B) switch on. Then I pressed the big button on the new Gliderol remote which made the LED turn off.

And hey presto. Pressing the top auxiliary button on the Gliderol remote made the gate open. I am not sure how the remote (or the gate actuator) knows to use the auxiliary button to work the gate instead of the main remote button. But hey, these are the things of electronic pixies and programmable fairies. Let’s leave some things unexplained so life is more interesting.