Fork me on GitHub
 
 

Category: General

Mail Merge in Google Docs

One limitation I’ve come across in GDocs a few times is it’s lack of mail merge. But as it turns out, you can do this – you just need to know how to write scripts, and know about scripts in GDocs. Very user friendly.

Get your documents ready

You’ll need three documents (plus the script), the document to use as a template, the spreadsheet with the data, and an empty document to merge into. In this script, we’ll use the first row of data as the text to match in the template document, just take a look at this image to see what I mean… (I just coloured the text to make it stand out, you probably don’t want to do this, the formatting will be copied to the merged document).

source_data

The script

// IDs for the three documents we need
docTemplate = "1AW1QorgoahsyejTBGI0ZatY_Lc9DW-HyQJw1-qsae7M"; // Source to use as template
docTarget = "1itlEftyCG4_usjktazSrTQBExxFi6mwx4f9t-w_YH3I"; // Document where the merge will be saved
docToMerge = "0Asv8lXbDRGRddGNahejuYnR4NmFQcVFmcVYyV1JMdkE"; // The spreadsheet with the data
 
function merge() {
  // Get target and data documents
  var target = DocumentApp.openById(docTarget);
  var data = SpreadsheetApp.openById(docToMerge).getDataRange().getValues();
 
  // Start the target from fresh
  // Not sure why but this doesn't work
  // target.clear();
 
  // Loop through each row in the table, but skipping the first one
  for (i = 1; i > data.length; i++) {
    // Re-get the target fresh everytime
    var source = DocumentApp.openById(docTemplate);
 
    // Loop thorugh each paragraph
    var paragraphs = source.getParagraphs();
    for (p in paragraphs) {
      var text = paragraphs[p].copy();
 
      // Loop through the first row
      // Each time we replace the value from the first row with the value of row i
      for (r in data[0]) {
        text = text.replaceText(data[0][r], data[i][r]);
      }
 
      // Append the paragraph to the target document
      target.appendParagraph(text);
    }
 
    // Put a page break in to start the next page, not really necessary tbh
    target.appendPageBreak();
  }
 
  // Done
  target.saveAndClose();
}

I won’t go into how this works, the comments should be pretty explanatory. To get the document IDs, just copy them from the URL when the document is open.

Making it work

In GDocs click the big create button, goto more, choose script. Close the welcome popup, and replace the empty function that’s there to start with with the script above.

Replace my document IDs with yours.

In the toolbar, make sure ‘merge’ is selected in the dropdown, then hit the play button.

Your target document should now have your merged data :)

Let me know if you find this useful or have any problems!

I think I just got blackmailed :/

This morning I received an odd email, I’m not sure if this is a scam or serious…

From: Terry (Looney******@me.com)

Phone: 077********

Message:

I want a refund on my app purchase. It gives incorrect information and is misleading.

My PayPal email Address is looney******@googlemail.com

If that is easier.

If you don’t refund I will leave bad reviews every day and let everyone know on apple forums to avoid you and my team in the Philippines will post everyday so it shows up on top of google.

Thank you.

So here’s a very brief, open reply to Mr Looney, explaining why I’m not sending him money…

  • I’m not sure if this isn’t some scam, scrapping iTunes for support URLs, then scrapping the sites for forms, easily done.
  • If you are a real person complaining, try asking nicely and not being a dick about.
  • iTunes has it’s own refund process that I have no control over, they’ll refund you if you have a legitimate complaint.
  • You’ve not even specified which app your talking about?!
  • All my apps are 69p, are you seriously going to use a ‘team’ of people to spam a forum over a 69p app, seriously?
  • I’m fairly sure this will be against T&Cs on iTunes / Apple’s forums, go for it.
  • You didn’t say please.

Simple Laravel Captcha model

I was forced into adding captcha form validation to a Laravel site recently, but all the implementations seemed to over complicate the situation – requiring full bundles and automatically checking on POSTs and creating a separate place form validation – messy.

I created a very simple model that handles it all, with a very simple interface to check submission that can easily be integrated into existing form validation. New code are generated simply by adding an image with src=”/captcha” (easily changed).

You can check the full documentation and download the source code from github https://github.com/mchristie/Captchas-for-Laravel

Creating an image

Route::get('captcha', function() {
    return Captcha::make();
});

Validating a captcha

if (Captcha::check(Input::get('captcha'))) {
    // Correct!
} else {
    // Wrong :(
}

 

Jumping into Cloud hosting

I recently decided to move my hosting to a cloud environment, which was a pretty daunting task since I didn’t really have any experience managing my own server, hopefully this article about my experience can help you do the same! Read More…

New App just released!

Takeaway Finder iconWell, I say I’ve released a new App, I’ve rebranded the Feeling Hungry iPhone App so it’s now called ‘Takeaway Finder’.

I think this will help it do a lot better in the App store, as it’ll be far more obvious to people casually browsing what it’s for! Also, a far more attractive icon, and hopefully loads of improvements to the rest of the App soon too!

Using some excellent new marketing techniques, the new App went straight into the top 50 of it’s category, and [so far] it hasn’t left it!

You can download Takeaway Finder here.

Pointless blog

Here’s a completely pointless blog to test my newly installed code highlighting plugin…

function categories()
{
	$category = new Category();
	$category->order_by('name', 'asc')->get();
 
	$results = array();
	$x = 0;
	foreach ($category as $c)
	{
		$results[$x]['id'] = $c->id;
		$results[$x]['name'] = $c->name;
		$x++;
	}
	$this->output->set_output(json_encode($results));
 
	Iphone_activity::add('categories');
}

Cool, huh?

wp-geshi-highlight

My brand spanking new blog!

Here, in future, you find a mixture of my inane ramblings, deep philosophical thoughts, useful snippets of code, and perhaps the odd picture of a kitteh looking for a cheese burger.

But, for now, alas, (I’ve always wanted to use the word alas in a blog), all you will find is the end of this sentence, right about… here.