Friday, March 28, 2014

Batch convert Word documents to .pdf files in Word 2007 and later

This is brilliant. "Faster" posted some vbs macro code in 2011 which uses Word 2007 and later to convert all files in a folder to .pdf files (or other formats, even on earlier versions of Word).

A few cautions: the original files are not modified, but the generated .pdf files are put in a sibling folder to the one you select. For instance, if you provide the path c:\docs\wordfiles, the pdfs will be created in c:\docs\wordfilesconverted. Also, make sure there is nothing but Word files in the folder you select, because it will try to convert any files it finds in the given path. Fortunately, it doesn't recurse into subfolders, so you can dump non-word documents into a temporary subfolder before you run the conversion.

For posterity, here is the code:
Option Explicit

Sub ChangeDocsToTxtOrRTFOrHTML()
'with export to PDF in Word 2007
    Dim fs As Object
    Dim oFolder As Object
    Dim tFolder As Object
    Dim oFile As Object
    Dim strDocName As String
    Dim intPos As Integer
    Dim locFolder As String
    Dim fileType As String
    On Error Resume Next
    locFolder = InputBox("Enter the folder path to DOCs", "File Conversion", "C:\myDocs")
    Select Case Application.Version
        Case Is < 12
            Do
                fileType = UCase(InputBox("Change DOC to TXT, RTF, HTML", "File Conversion", "TXT"))
            Loop Until (fileType = "TXT" Or fileType = "RTF" Or fileType = "HTML")
        Case Is >= 12
            Do
                fileType = UCase(InputBox("Change DOC to TXT, RTF, HTML or PDF(2007+ only)", "File Conversion", "TXT"))
            Loop Until (fileType = "TXT" Or fileType = "RTF" Or fileType = "HTML" Or fileType = "PDF")
    End Select
    Application.ScreenUpdating = False
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set oFolder = fs.GetFolder(locFolder)
    Set tFolder = fs.CreateFolder(locFolder & "Converted")
    Set tFolder = fs.GetFolder(locFolder & "Converted")
    For Each oFile In oFolder.Files
        Dim d As Document
        Set d = Application.Documents.Open(oFile.Path)
        strDocName = ActiveDocument.Name
        intPos = InStrRev(strDocName, ".")
        strDocName = Left(strDocName, intPos - 1)
        ChangeFileOpenDirectory tFolder
        Select Case fileType
        Case Is = "TXT"
            strDocName = strDocName & ".txt"
            ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatText
        Case Is = "RTF"
            strDocName = strDocName & ".rtf"
            ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatRTF
        Case Is = "HTML"
            strDocName = strDocName & ".html"
            ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatFilteredHTML
        Case Is = "PDF"
            strDocName = strDocName & ".pdf"

            ' *** Word 2007 users - remove the apostrophe at the start of the next line ***
            'ActiveDocument.ExportAsFixedFormat OutputFileName:=strDocName, ExportFormat:=wdExportFormatPDF
           
        End Select
        d.Close
        ChangeFileOpenDirectory oFolder
    Next oFile
    Application.ScreenUpdating = True
End Sub
Activate the Developer tab in Word, then open up the vbs console (or create a macro) and paste this code in (make sure the lines don't wordwrap like they do on this page), then run it. Assuming you're running Word 2007 or later, be sure to delete the apostrophe where indicated.

For more details, check out the original post.

While we're on the subject, may I further recommend PDFbinder as a free program which allows you to merge many pdf files into a single multi-page file. And also Compress PDF, a free online service which compresses your .pdf file sizes.

~Till next time!

Labels: ,

Thursday, February 13, 2014

Setting up AutoCAD with common support files while allowing some customization

This is going to be another dense post, intended mostly to remind myself of how everything is set up, but posted also to help people already familiar with the way AutoCAD is deployed and customized. Please make sure you know how to work with cuix files and load them via the customization file portion of the options dialog before proceeding.

Our firm recently rolled out AutoCAD (and BDS) 2014 to our users. For the past few releases (since 2008, I believe) I've been very interested in using common support files stored on the network, but have always had to come back from the edge because of one or two limitations such a setup would impose: the inability for users to have their own .pgp file (command alias list) has always been a big one among these.

This time however, I believe I finally have figured out the "right" way to do this stuff, and I wanted to document it here while it's still fresh.

First of all, the benefits of sharing support files. It has happened in the past that, for instance, I create a new line type for a job, which ends up being very useful and I want to make a part of our library for everyone. Or a new hatch pattern. Or change some buttons on our custom ribbon tab, etc. I used to have to make the change to my own support files, then copy them into the deployment folder (for any future re/installs), then send out an e-mail to everyone with the location of the updated files and ask them to manually copy the new files into two locations on their local machines. Both of these locations were within (different) hidden directories, and so depending on the machine, had to be manually typed in, and one of the locations was a path that's about 18 miles long. That was the only way of ensuring that they had the new files, both now in the future when an inevitable new Windows profiles might be created and set up using AutoCAD's userdatacache.

Obviously this is a painful and annoying process, for everyone.

The promise of shared support files, on the other hand, is that I (as an administrator, not a typical user) can make a change, once, and upon the next launch of AutoCAD, everyone's files are automatically up-to-date since all our installations are literally using the same files. Obviously in the case of laptops (which will be asked to run AutoCAD away from network connectivity) we have to make use of offline files (and for the love of cheese, do this via Windows Policy using Administratively Assigned Offline Files), but we've already been doing that, so that literally took no additional effort in our case.

But AutoCAD's deployment routines aren't so fine-grained that I can specify that acad.cuix, our enterprise cuix, hatch file and linetype files should be shared, but that (for instance) the .pgp file shouldn't be. And even if it were, it's a pain for the users to have to navigate through 18 layers of folders to get at their .pgp file if they want to change or add a command alias.

The first discovery (I would link to a forum post if I remembered what it was, but it was a rather oblique reference to this process anyway) is that AutoCAD has a list of support file paths, and it treats the list as a hierarchy, going down the list until it finds the file it's looking for, at which point it stops looking for it. So even though our shared support file path does include a single acad.pgp file, nobody's machine is actually using it. Why? Because as part of the AutoCAD installation, I told it to create a new folder at c:\acadsupport and stick another acad.pgp file in there. Then I put c:\acadsupport at the top of the list of Support File paths. Any files in acadsupport are now available to AutoCAD (and functionally override whatever identically-named files may be in the shared support file directory on the network).

That seemed like the end of it ... until someone asked how to customize their Quick Access Toolbar. Ouch. You see, I'd created a "default" Quick Access toolbar in our enterprise cuix file and added it to the workspace I'd created in the same enterprise cuix file for everyone to use. (This workspace has our custom ribbon tab, for instance). And the problem is that everything in the enterprise cuix is read-only (presumably so that one person can't change everyone else's workspace in the event that the main customization file isn't shared). So the Quick Access toolbar was forced to be identical and unchangeable for everyone...which is contrary to the way most people are used to using those toolbars (for instance, in Office).

The solution ended up being creating an additional cuix file that contains nothing but a Quick Access Toolbar. I used the transfer tab of the CUI window to copy the Quick Access Toolbar into a new file, and saved the resulting cuix file as quickaccess.cuix. That way it is set up with some default buttons for convenience. Then I included it as part of the AutoCAD deployment to get installed to c:\acadsupport.

Since I'd already included a quick access toolbar in our enterprise customization file, I first had to edit the workspace definition so that it didn't include any quick access toolbar. If you don't find yourself in the same situation as I did, skip this paragraph. (By the way, the easiest way I found to edit the enterprise cuix file is to set it as your main customization file and set acad.cuix as the enterprise customization file temporarily). In the left side of the CUI window, expand your enterprise customization file and under Workspaces, highlight your workspace. Now in the right side of the window, right-click the quick access toolbar and choose "Remove from workspace". Then click the "Customize Workspace" above the right side panel, and uncheck the box next to the quick access toolbar on the left side of your custom CUI file under "Quick Access Toolbars". Now exit customize workspace mode, and right-click the quick access toolbar on the left side of the window and choose to delete it from your cuix file entirely.

Now you're ready to link in a personalizable quick access toolbar. Make sure acad.cuix is set to your main customization file. In the CUI window, at the bottom of the main customization file tree, there's an entry labeled "Partial Customization Files". Right-click this item and load c:\acadsupport\quickaccess.cuix. Since everyone is sharing this acad.cuix, all their installations will now look for this file. (if it doesn't exist, it won't pop up an error or anything, it will just note that it's unresolved).

Now you need to update the workspace stored in your enterprise file to include the quick access toolbar stored within this partial cui file. Set your enterprise cuix file as your main customization file (swapping acad.cuix over to the enterprise customization file node at the same time so it's still available), then get back into the CUI dialog. Find and select the workspace you want this quick access toolbar to show up in, then on the right panel click the "Customize Workspace" button. On the left panel, scroll down to the partial cui file, expand it to the quick access toolbar item, and check the box next to the default quick access toolbar you made. It should show up on the right panel now under Quick Access Toolbar. Exit customize workspace mode. Now put acad.cuix back as the main customization file, and your enterprise cuix file as the enterprise customization file again.

One final step: to make sure the settings get saved, set your current workspace to your enterprise workspace again.

Now each user should be able to freely customize their own quick access toolbar however they want...their personal toolbar is saved in c:\acadsupport\quickaccess.cuix (you should see the timestamp on that file update whenever they add or remove a button). The shared acad.cuix file is set to look for that file, and the toolbar contained therein is used by the workspace saved in the enterprise cuix file. (By the way, you can't load quickaccess.cuix as a partial customization file under your enterprise file, because remember that it and anything it loads is marked read-only).

*whew*

Of course, you could simply store the workspace and any of your enterprise customizations in the shared acad.cuix, but (although I don't know the actual reason it's set up this way) it does seem prudent to keep your customizations in a separate file from all of AutoCAD's defaults - especially since that file is set to read-only by all your users. acad.cuix is easy enough to restore to default, but your own customizations might get goofed up beyond help if your users discovered they had the power to get in and tweak things.


The final result: here's how my CUI window looks. The Quick Access toolbar is stored in a cuix file in each user's local c:\acadsupport directory (and thus customizable and personal), which is loaded by the shared acad.cuix and used in the workspace stored in the shared enterprise customization file.

Labels: ,

Tuesday, August 21, 2012

Using DFS shares from Metro

I like Windows 8. I really do - and I can't wait for good tablet hardware to come out with it's release.

However, the interface-formerly-known-as-Metro, being a v1.0 product, has a few issues which I find to be more than annoying.

One is that it doesn't appear to be possible to use Unicode characters in any Metro apps ... bye-bye Metro Remote Desktop! (I use nice, strong passwords, that's why).

Another is that, incredibly, the Metro file picker doesn't understand DFS shares. That is, it sees the share itself, since I've mapped it using Group Policy, but when you open it to browse, all your shares within are gone - the root appears to be completely empty!

One workaround is to click the "File" label in the top-left of the dialog, and select instead "Network". But then you have to type in the UNC path of the share to browse. That's a lot to ask of a user - and defeats all of the reasons to use DFS!

I've just found another workaround, with the help of an article at The Super Site for Windows and the Windows 8 help file. To start, understand that many of the Metro apps expect to work within the structure of Libraries. Now, if you can add your DFS shares to an existing (or new) library, you're done. This is the best solution so far, because it'll use the mapped address (for instance, Z:\share1) instead of a non-dynamic UNC path (for instance, \\server23\share1$). Using the mapped address means it's dynamic and keeps working if you redirect the shares to a new location.

But you can't add a network location unless it's indexed. Easy enough if the shares are small- make them available offline! But if you can't / don't want to make all your DFS shares available offline, here's the official way to, "Add a network folder that isn't indexed to a library":
(From the Windows 8 help file):
  1. Tap or click to open Computer.
  2. Create a folder on your hard drive for your network folders, for example c:\share.
  3. Create another folder within that folder, for example c:\share\music.
  4. Select the subfolder you just created, tap or click the Home tab, tap or click Easy access, choose Include in library, and then select the library to which you want to add the folder.
  5. Delete the folder.
  6. Swipe in from the right edge of the screen, and then tap Search.
    (If you're using a mouse, point to the upper-right corner of the screen, move the mouse pointer down, and then click Search.)
    .
  7. Enter cmd in the search box, and then tap or click Apps.
  8. Press and hold or right-click Command Prompt in the search results, and then tap or click Run as administrator.
  9. Enter mklink /d, and then enter the path of the folder you just deleted and the path of the network folder. For example, mklink /d c:\share\music \\server\music. This creates what is called a symbolic link.

Lest I forget to mention it, Metro apps also don't appear to understand symbolic links themselves (probably the reason it doesn't understand DFS shares), or even normal SHORTCUTS, so you can't just make the dynamic links in a folder on your desktop and get there that way. They have to be included in a library to resolve.


Obviously, this solution is less than ideal for a few reasons:
1) The only way I can think of to avoid having to do this manually per-user, per-machine, is to run a logon script that copies the pre-formed *.library-ms file to Libraries AND creates the symbolic links.
2) It bypasses DFS entirely, so the shares aren't dynamic, if you need to hand off traffic or change hosting servers for a share
3) When you're browsing for a file in a Metro app, it doesn't group by location; you see everything from all the roots of each library location, arranged alphabetically.
4) And just to call out the elephant in the room, yes, it's 2012, and the official way of solving this problem in Windows 8 still starts with, "open command prompt". Unbelievable.


Still, it's a start. Kind of.

Labels: ,

Monday, April 11, 2011

NASA Stereogram

I just made this for fun today- it's a stereogram made up of all the names of NASA astronauts, as listed on Wikipedia on April 7, 2011. They read in columns; the leftmost column is unaffected by the stereogram, so you can read all the names. Now, use the wallpaper method to view the stereogram (that is, not the cross-eyed method) and see what you can see :)


If anyone's interested, I used Excel to pare down the copied list from Wikipedia, then ran a custom AutoIt script I made a year or so ago for creating ASCII stereograms. Finally, I copied the text into AutoCAD so I could have ultimate control over the character width and spacing, and exported as a .png from there.


ASCII stereograms are fascinating to me, since you can actually analyze it and understand how your brain makes it work. The fact that your brain processes the anomalies to assemble a 3-d image almost instantly, is just stunning to me. What a design!


Edit: Here's another one- same basic process, but I made up a more intricate pattern this time. Just in time for the 50th anniversary of manned space flight and the 30th anniversary of the first shuttle launch!

Labels: ,

Thursday, February 3, 2011

Windows Phone: XML as a source

The post at http://weblogs.asp.net/scottgu/archive/2010/03/18/building-a-windows-phone-7-twitter-application-using-silverlight.aspx is incredibly useful to illustrate how to parse an online XML feed to populate a ListBox control dynamically (including the "bodies" of a Panorama page, which are just ListBoxes).

...and here is a page that may do the same for JSON: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer(v=vs.95).aspx

Labels: , ,

Saturday, October 23, 2010

Windows Media Center custom menu strip

My hopes of having a real Windows Media Center set-top box be released this year having been dashed, and having for various reasons begun looking into other online media consumption services for the TV, I've started to try and plug in as many services into Media Center as possible.

Third-party support for plugging them in is a bit spotty from app to app, with some of them adding themselves to the "Extras" menu (Boxee), and some of them creating their own custom menu on which they sit all alone (Hulu).

Finally today, I found a wizard called WMCWW that lets me (very) easily create a new custom strip and place as many other plugins on it as I want, then even delete the custom menus that those services created (Hulu) so I don't see duplicates.

Works on x86 x64 Windows 7...yay!

Labels: ,

Monday, August 16, 2010

Group photo sharing through yogile.com

Here's a nearly universal truth: if a picture of a kid exists, that kid's parent wants a copy. Really self-controlled parents might go ahead and delete pictures that are blurry or where their kid is clearly not the subject of the picture. Maybe. But they want to make that choice themselves, and that means that any time you get a group of kids together in this age of ubiquitous digital cameras, there's going to be about 250 pictures per half-hour that every parent is going to want a copy of, from every other parent.

If said parents don't want to trust that everyone else will remember to include them in the list when sending out pictures (which may or may not happen), the solution has historically been for the event-planner to tell everyone to e-mail all the pictures to them, at which point they will make copies of all the pictures and get them back out to all the attendees.

Here's my question for you: has that ever worked out for you? In my experience, the absolute best scenario is that most of the parents will get copies of their pictures to the planner. But then the planners get to figure out when to draw the line of, "everyone who's going to send pictures, has sent them". And not only is it very easy to keep procrastinating, "just in case more come in", they really have no motivation to get those picture dispersed back out. After all, said planners now have all the pictures, so now they're happy, and their attention quickly turns to something else. And if they're really ambitious and actually decide to really get it done, they'll always end up being shocked at how many kids are in the pictures, and therefore how many copies they'll have to make and re-disperse.

Then along came services like Facebook, Flickr, Snapfish, Photobucket, etc. These well-meaning services have the right idea, which is to allow everyone to contribute photos into a single album, then provide everyone access to the pictures when they want to check in on their own. But they all require you to have an account to contribute and/or to view the album. And that's really a pain, as you're asking all these frazzled, non-techie parents to try and maintain all these different accounts, many of which they'll only use once. What happens is that if they register, they only end up spreading their invariably re-used credentials across the digital world, then forgetting that they even have that account. (Of course, I know that you use a unique log-on and password for every site for which you have an account, right?) And then they wonder why they get all this spam in their e-mail for the next twelve years.

Well, this morning I heard about a service that really makes a lot of sense. Yogile.com allows you to create a photo album for an event and optionally password-protect it. You get to pick a unique web address and e-mail address for this event. Then when you ask people to send pictures, they can either e-mail them as attachments or upload them at that site. If it's not a protected album, they can also view the photos from the event at the address you picked. And the best part is, anyone can contribute. Nobody needs to register if all they want to do is contribute pictures and view public albums. And yogile also makes sure that any pictures added to your album are sent to you (the album creator), so you don't even have to remember to log on and check for new additions.

It looks like it's free for up to 100mb, and $24.95 per year if you want unlimited storage with an ad-free interface. Here's the summary of their service from their page:

•Lets multiple people contribute with ease.
•Add photos as e-mail attachments or uploads through the site.
•Customizable URL and e-mail address per album, to share with anyone who wants to add photos.
•No need for these users to register, keeping the process simple

So I haven't used it yet, but this is just the type of thing I've wished for in the past, so you can be sure that I will before too long. And I just wanted to share (and post it so I can remind myself of it when I do need it).

Labels: , ,

Wednesday, August 11, 2010

Using PlanningCenterOnline.com's API with PHP

It's been a bumpy road, but thanks to Scotty at Planning Center Online, I've finally got their API working through PHP. In my case, I've got it returning info to render a custom Facebook Application for the church's Page, listing all the songs we sang during the previous weekend's services, and giving various links using the song names (search iTunes, Amazon, Zune or Pandora, etc). So I wanted to document the steps here, both in case I have to go back later, and for anyone else trying to do something similar.

First, a few requirements.
1) You will need a web server running PHP5
2) I assume that you have an understanding of XML and HTML- writing an app is not something that should be for first foray into the world of online programming.
3) If you need a database (more on that in a minute), you need to know how to access it and configure it yourself.
4) Knowing PHP is going to help you (quite a bit, probably), but for the record, I am one of those who doesn't know PHP, so it's entirely possible to do this, if you have other programming experience. If this is you, let me give you two tips that turned on a light bulb for me: the command -> in PHP is somewhat akin to a dot in other languages like Javascript...$str->doThis() would be more or less the same as $str.doThis() in other languages; it takes the variable and applies a function to it. Also, a dot concatenates strings instead of a plus sign or ampersand in other languages.

The mile-high overview starts at http://www.planningcenteronline.com/home/api . As they note, they use OAuth 1.0a for authentication, so you need to e-mail them with details of your app to get a Consumer Key. The e-mail address is listed on that page, I'm not going to repeat it here 'cause I want you to go look at that page and find what info they want you to send them. After all, they may change the address or information they need in the future.

Now, as they say on that overview page, they've provided some sample PHP files- so pay those files a visit.

1) You need to download four files: OAuth.php, common.php, index.php and complete.php . OAuth.php and common.php are just include files, the only thing you need to do with these is to edit common.php to enter your app's key and secret (unchanging random strings provided to you when you e-mail them as I noted above), and to point $callback_url to complete.php.

Now I need to explain the functions of the other two files, because they aren't what you might initially expect. Complete.php is actually your app itself. Loading index.php on the other hand, actually starts the initial authorization process, and should only be loaded once per user. But at the end of that process, it will use $callback_url to send the user back to complete.php. So you might want to rename index.php to something like requestAuth.php and complete.php to the file name you actually want people to load, if you wanted to help keep it straight in your mind. That said, I'm still going to refer to them by their original names throughout this entry.

2) Now you need to upload OAuth.php and common.php to a directory on your web server where PHP will be looking for include files. On my server, this is under admin/core, but yours will probably be somewhere else. But don't assume that all four files can just be uploaded to a single directory and expect php to be able to find them.

3) Now it's time to figure out how you want your app to work. If you want it to just create a page that looks the same and has the same data no matter who loads it, you might want to create a user in your organization's PlanningCenterOnline account that has full viewing rights. That way your app has access to any info you want, but if something goes wrong, the account doesn't have the power to affect other users, change or delete data, etc. With this method, YOU will be loading index.php once, and logging in using that new account, and authorizing the app to use that account. The end users loading the page don't ever have to authorize anything.

Let me talk for a minute about apps that instead give each user different data based on their own account (showing them their calendar, listing songs only on weekends they're scheduled for, etc). For this app, you don't need to make a new user account, since each user will be authorizing the app to use their own account. You're going to need to store users and their authorization keys in a list or some kind of database. I still think this article will be valuable to you so that you have an idea of where everything goes and what it does, but I'm not going to go into specifics on how to create this type of app or working with the database you'll need. But here's a high-level overview of what you're going to need to do for this type of dynamic user-specific app:

-Your users will probably be coming in and hitting your complete.php page first, since once it's authorized that's where they'll need to be going. You need to have complete.php check your database or list to see if they have authorized the app before, and if not, redirect them to index.php.
- Once they authorize through index.php, you need to store their credentials so they don't have to authorize again. You can either do this at the bottom of index.php before they return to complete.php, or you can point $callback_url in common.php to a new php file that does nothing but store their creds, then redirect them to complete.php itself. That way you'd keep complete.php simpler- a simple, "if they're not in the database, redirect to index.php" condition.
- Everything else will be mostly the same as I outline below- instead of hard-coding the key and token into the php code, you'll just be using the stored strings in your database.

Now back to assuming that your app will display the same data to everyone:

4) Edit complete.php like so:
- Delete everything below line 51. That is, delete everything from
// 4. Set Person id for example 1 and example 2
down, but leave the ?> tag in the last line intact. Now at the end of the file (but above the ?> tag), enter these two lines:
echo $access_token['oauth_token'] . "<br />";
echo $access_token['oauth_token_secret'];
Now upload index.php and complete.php to your web server.

5) Fire up your browser, and load your index.php page. It will immediately bounce you to PlanningCenterOnline and ask you to log in (if you're not already). Log in to whatever account you want the data to get pulled from. Once you're logged in, it will ask you whether you want to allow your application access to your account. Check "Authorize access" and click "Save changes". It will redirect you to complete.php, and there should be two lines of random characters. The first line is the token proving that this account has authorized access to this app, and the second line is the secret to verify the token is legitimate. You need these strings in the next step.

6) Now edit complete.php again. This time, delete everything below the two require_once lines at the top of the file (again, leave only the ?> line at the bottom of the file intact). Now between the second require_once line and the ?> line, put in this code:
$test_consumer = new OAuthConsumer($key, $secret, NULL);
$access_consumer = new OAuthConsumer('abcdabcdabcdabcdabcd', '1234123412341234123412341234123412341234', NULL);
Now replace the "abcd..." string with the token that showed up a moment ago on complete.php (it's the top line). And replace the "1234..." string with the secret string that was below it.

(if you're storing these keys in the database, this is obviously where you want to fetch the data for the current user and replace that in, instead of hard-coding it into the php here).

7) Your app should be able to authenticate sucessfully now, and make requests to modify or read data, based on the permissions of the authenticated user in PlanningCenterOnline. To make sure it worked, add in the following lines just above the ?> tag:
// build and sign request
$request = OAuthRequest::from_consumer_and_token($test_consumer,
$access_consumer,
'GET',
'https://www.planningcenteronline.com/organization.xml',
NULL);
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$test_consumer,$access_consumer);
// make request
$response = run_curl($request, 'GET');
// display request
echo $response;
Now upload complete.php again, and browse directly to it again. This time, you should see a whole lot of XML output providing you all the data about your organization. It should look similar to what you see in their example. If you do, it worked! Not too bad, huh?

8) Now for the fun part: you need to actually write your app! Fortunately, this is a lot easier than all the OAuth stuff. See how, in the lines above, we chose to, "get" the URL https://www.planningcenteronline.com/organization.xml? GET means that we want to read, not change, the specified data. The URL is documented under "Organization API" at http://www.planningcenteronline.com/home/api. So look through all the APIs (Plans, People, Songs, etc) and look at their samples to see what output you can expect, in order to extract the data you want to show in your app. Anytime the URL on one of their APIs includes the number 1, you need to understand that's actually a placeholder for an ID you need to get from one API level "up".

So for my app, which lists all the songs sung in a particular week, I have to start at the Organization API and extract the ID of the correct "service type". (I know which service type I want because each service type has a "name" tag associated with it as well, and that's the name I'm used to seeing in Planning Center). Say that ID was 1234.

Now look at the Plans API. The URL you need to GET to get a list of available plans (in my case, plans = weekends) is https://www.planningcenteronline.com/service_types/1/plans.xml, so I replace 1 with the 1234 that IDs the service type I want to look into, and build my query to GET https://www.planningcenteronline.com/service_types/1234/plans.xml instead.

That returns a list of available plans, so I need to parse the list to find the ID of the plan I want to examine. Then replace that ID into the URL for listing all the elements of a service. For my app, I then parsed to find the IDs of all elements which had a "type" of "PlanSong", and looped through the list, replacing each ID into the URL of the Songs API to extract the titles.

Now, I did find out that there is at least one argument you can put on the end of the URL to change the output- since my app deals with plans in the past and the default return from the Plans API is only future plans, they told me instead of running GET on https://www.planningcenteronline.com/service_types/1/plans.xml, I could run it on https://www.planningcenteronline.com/service_types/1/plans.xml?all=true instead. See the extra parameter there on the end? all=true tells it to return past services as well. And they told me if there were multiple parameters to use an ampersand (&) between the keys, which along with the question mark before the first key, is pretty typical. But I was never able to get an answer or find a list of all the available parameters for the different URLs, nor did brief experimentation with other logical key/value combinations yield anything else that worked. But if there's some information you need that it won't return, write 'em up and ask them- there just may be a parameter you can add that will do the trick for you! And if you learn of any others, please leave a comment here!

Though a detailed description of looping through the XML is more than I want to cover in this post, I'll at least point you in the right direction. I store the XML data in $response, as you saw in the initial Organization API example we used to make sure authentication was working. So here's how I display the date of the service whose songs I'm listing:
$xml = simplexml_load_string($response);
foreach($xml->children() as $child)
{
if($child->getName() == 'dates')
{
echo 'Songs from the ' . $child . ' services';
}
}
I hope that helps someone who wants to use the API with PHP!

Wednesday, March 24, 2010

Printing to a shared XP printer from Vista or Win7

Ran into a situation this morning that probably isn't that uncommon, but I could only solve it by combining information from several places- none of which had the full easy solution.

The problem is we have an old printer (with only a parallel port) hooked up to an old XP-based computer. It's shared on the network, and the firewall is set to allow file and printer sharing, so I thought all was good. But when I go to a Vista or Win7 machine and try to connect to it, I get an "Access Denied" error. Figuring it was a driver issue, I went to the XP machine and tried to add the appropriate drivers, but you can only provide drivers for older OSes, not newer ones.

The answer, I finally figured out, is pretty simple, and doesn't require you to change what computer the printer is hooked up to, even temporarily.

1) Go to your Vista or Win7 machine

2) In your "Printers" folder, click "Add a printer".

3) The wizard asks what type of printer you want to install. Choose "Add a local printer". (Yes, I know it's technically not a local printer, but if you choose "network printer", it'll try to pull the drivers from the XP machine, as before, giving you an error)

4) The wizard asks what port it should use. Choose "Create a new port", and choose "Local Port" as the "Type of port".

5) When it prompts you for the port name, type in the computer name and printer share name, in UNC format: \\computer\printer (replacing "computer" with the computer's network name, and "printer" with the printer's share name). This is what tricks the computer into believing a network printer is actually a local printer.

6) Proceed through the "Install the printer driver" screen as usual, choosing the Windows-provided driver from the list, from Windows update, or from copy of the driver you've downloaded with the "have disk" button.

7) Name the printer anything you want (or keep the default name)

8) Now the drivers will be examined and installed automatically by Windows. If they're not signed drivers, it will pop up the usual warnings. That would happen even if you were installing a true local printer, so do whatever you'd do at those dialogs if it were a local printer.

9) Share the printer if you want...you could then use the share from this machine to keep from having to do this with all your Vista/Win7 machines, but then you're requiring that TWO machines be available if you wanted to print from a third machine...since it would need to talk to your Vista/Win7 machine, which would in turn need to talk to the XP machine. It's probably more reliable to choose to not share the printer from the remote (Vista/Win7) computer.

10) Print a test page to confirm it worked, close the wizard, and you're done!


Hope that helps someone!

Labels: ,

Wednesday, July 15, 2009

NASA Image of the Day Desktop Slideshow for Windows 7

Using the information I compiled and posted previously, and in honor of today's scheduled shuttle launch, I made a Windows 7 Desktop slideshow theme file that uses NASA's Image of the Day (large) feed to decorate your desktop wallpaper with daily-updated pictures of Space and NASA operations.

Unfortunately, due to how NASA runs their image feed, you can't download previous days' images into your slideshow...so the first day you load the theme, there will only be one picture. The next day, it'll flip back and forth between the new day's image and the previous one, etc. After about a week, it'll have a good number of images to draw on for your slideshow.

To control how many images are kept for the Desktop Slideshow, open up Internet Explorer 8 after having loaded the theme. Open up the "Feeds" tab of the "Favorites" window, and right-click on the feed called "http://www.nasa.gov/rss/lg_image_of_the_day.rss" choosing "Properties" in the context menu that pops up. Under the "Archive" section of the properties sheet, you can set the number of attachments (pictures) you want to keep.

The nice thing is, you can install the theme, causing IE to subscribe to the feed, then go back to whatever theme you'd been using before. Even though the theme isn't active as your Desktop Slideshow, IE will continue to download each day's picture in the background (keeping a default of 200 max). So you could come back a week later and set the Nasa Image of the Day theme as your background again, and it'll have a far greater number of pictures available to shuffle between.

One final note: it took my computer 5 minutes or so to download the picture, during which time my desktop was a plain black background. Once it downloaded, it just faded in, nice 'n pretty.

Enjoy!

NasaIotD.theme

Edit: I found a way to "seed" the feed with previous images so that you can have more pictures than just the number of days you've had the theme, and it's not horrible a horrible process, either.

Once you're subscribed to the feed, right-click it and choose "Properties", as documented above. In the "Update Schedule" section, there's a checkbox that'll be checked to "Download Attachments", and next to it, a button labeled "Show files". Click the button, and you'll see all the pictures already downloaded from that feed (probably only one picture, if you've just subscribed to the feed). Copy that folder's path to your clipboard, then you can close that window, as well as the feed properties dialog. Now go to NASA's Image of the Day page. Grab the large versions of any past pictures you want to include, and right-click on the link offering to download the full-size version, choosing "Save target as...". When it prompts you for a path, paste in the feed-specific path you just copied, and save the picture there.

Now your slideshow has many more pictures available to rotate between! (If you want to make sure it worked, go back to your Personalize menu from the desktop, and re-select the Nasa Image of the Day theme. It should rotate to one of the new pictures you just added).

Note that you don't HAVE to use only NASA's Image of the Day pictures to seed the feed; you can put any pictures from any source you want to into that folder, and it'll get included in the rotation. It just kind of makes more sense to use something from the same feed :)

Labels: , , , , ,

Wednesday, June 3, 2009

RSS-based Windows 7 desktop slideshows

I know the title of this post is rather obtuse, but this is something I'm excited to see has been included in the forthcoming Windows 7.

Windows 7 finally has native support for wallpaper "slideshows"...that is, you specify a GROUP of pictures you want to cycle smoothly between at the interval you choose, rather than having to always look at the same picture on your desktop.

What I didn't know until this blog post however, was that you can also make/choose a theme that points to an RSS picture feed for the picture sources. That means, we can make a file on our website that points to some high-res pictures of Kate, then send a small .theme file to our family. They double-click on the .theme file, and their desktop will begin showing a slideshow of some of Kate's pictures that we chose for that purpose. Later, as we publish more pictures, they will automatically be included in our family's wallpaper rotation, with no extra work on their part.

What a nice way to share pictures effortlessly! Now if only there was a screensaver with that capability...

Edit: apparently there is at least one such screensaver, but it's a visual C# sample project, not a completed screensaver you'd want to run. I tried it out, and it's iffy at best, not to mention that it's certainly only for geeks who are not of the faint of heart). I still think this is a great idea that would go over very well with grandparents, for instance ;-)

From the Engineering Windows 7 blog:

Enthusiasts can create a theme where the desktop background slide show points to an RSS photo feed. For example, my sister lives across the country and we only see each other about once a year. An easy way for me to keep her up to date on my family is to send her a Windows 7 theme which points to my RSS photo feed. When I upload new photos they will appear on her desktop automatically.

Because there are a few different ways to create an RSS photo feed, the process to include an RSS photo feed in a Windows 7 theme will only work if your RSS photo feed links to the high resolution photos using the “enclosures” method. The feed should only reference picture formats such as JPEG or PNG. Due to this limitation themes must be created manually when including an RSS photo feed.

So, to create one of these themes you can follow these steps:

Download the template from MSDN.
Open the template using Notepad.
Replace {themename} with the name you want to appear in the Personalization Control Panel themes gallery.
Replace {rssfeedurl} with the full path to your compatible RSS photo feed.
Save the changes as a file with the “.theme” extension.


After that, you e-mail your friends and family that .theme file and all THEY have to do, is double-click on it and choose to set it as their theme. All the hard stuff (the above steps) are done on your (the creator of the feed/publisher of the pictures) end. However, I personally expect that online photo services will pick up on this capability very soon and starting offering you a .theme file download for all the pictures you've uploaded to their site, taking the burden of all that hard stuff off you.

Very cool stuff.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Update: I just tried this, and it works very well, except that it seems to be pretty picky on using only really well-formed RSS feeds: the feeds through Picasa, Photobucket and Webshots, for instance, didn't work. However, Flickr's feed did work. Even pictures which are oriented the "wrong" way (usually portrait [tall] instead of landscape [wide]) can be told by the .theme file configuration to crop and resize, so nothing gets "stretched" or "squashed" and it still fills the screen. There are other options too, naturally.

I love it! :)

BTW, here are my "test" files that worked for me. Open Kate.theme on Windows 7 to see it in action! (I'm not going to be updating these, so don't expect the pictures to be updated past the 12 pictures from March I used)
You don't need to download KateDesktopSlideshow.xml, but I provided it in case you want to see the minimum required for a working RSS file (right-click it and download it, rather than opening it in your browser, to see the codes). The pictures are pulled from the Kate pictures section of our website.

Kate.theme (Note: this theme won't work anymore; you can download it and set it as your theme, but it won't find any pictures. Since we migrated our site fully over to blogger's servers, the feed I used in this theme is no more).
KateDesktopSlideshow.xml

One more edit: I just discovered a lame side-effect of having an RSS-based desktop slideshow...it subscribes you to the slideshow's feed in IE and Outlook (and the RSS gadget, and anything else that ties into the "shared" Windows RSS feed library). So now I get notifications in IE and Outlook whenever a picture is added...nice if that's what I want, but in my case, I don't want that. I wish it were kept separate.

Note you can delete that folder from Outlook with no problem, but if you delete the feed from IE's favorite/feed list, the slideshow stops rotating and just stays on whatever the last picture was to show.

Labels:

Tuesday, June 2, 2009

Microsoft Outlook "Forgotten Attachment Detector"

I'd previously blogged about a third-party plugin for Microsoft Office Outlook that detects and reminds you if you seem to have forgotten to attach a file to an e-mail. Last week, The Road To Know Where linked me to an announcement that Microsoft released a plugin of their own for Outlook 2007 that does the same thing. I'm more inclined to trust Microsoft Labs' version ;-)

The "Forgotten Attachment Detector" Add-in for Outlook 2007 checks for keywords that indicate you’ve forgotten to attach an attachment. If it detects this, it notifies you and gives you a chance to correct any mistakes.

Monday, May 25, 2009

Media Center Plugins

Google Maps for Media Center (confirmed working in Vista- you have to save it in "%userprofile%\AppData\Roaming\Media Center Programs" or whatever your equivalent path is. For using it on an extender, use c:\users\mxc1\AppData\Roaming\Media Center Programs or equivalant.

=========

Personally untested, intriguing plugins:

Yougle (This one is supposed to bring online streaming video services to the media center (You Tube, etc). It doesn't list Hulu.

Media Control (This plugin is supposed to give better control over captions, fast-forwarding videos, etc)

Labels: , ,

Friday, May 22, 2009

Installing Windows 7 on netbooks with no optical drive

This is based on information I found here, but modified slightly to a nicer process, in my opinion :)

The problem is that installing Windows 7 (Beta and RC confirmed, RTM likely to be the same) requires a DVD drive, which many netbooks don't have. The good news is that you can still install it to these computers (assuming they meet the minimum requirements), you just have to make your own bootable media. Here's how: (Note I've done this on an Acer Aspire One netbook, but the steps are similar for other computers).

Step 1 - Download or acquire the Windows 7 iso or DVD. I personally like burning the ISO to DVD, rather than mounting it, but if the only computer you have is your netbook, you'll clearly need to download the iso and mount it without burning it. For burning the ISO on XP and Vista, I recommend the ISO Burner Powertoy. If you're running a flavor of 7 already, it's got native ISO burning capabilities. If you're going to just mount the iso as a drive directly, you'll need something like Daemon Tools (and you need to be somewhat of a geek to follow their instructions).

Step 2 – We need a device the computer can boot from. I've had better luck with SD cards rather than USB drives, personally. The specific one I've used was a 16GB Micro-SD card in an SD adapter, but I've also loaded up an 8GB SD card I got for $25 (see my previous post about the Wii menu upgrade and the card I got for that), and it worked too. Regardless, you need a drive BIGGER than 4GB. Note not all computers can boot from SD cards, though...make sure you confirm your computer's boot options. I used an Acer Aspire One netbook though, and it can boot from SD.

Plug the drive into a computer (I recommend a computer other than your netbook so you can use the Windows 7 DVD physical media, but it's up to you).

Format the device you want to boot from to get it all nice 'n clean. I recommend a quick format with NTFS file system, but I've heard Fat32 works as well. You can do this by right-clicking the drive in My Computer and choosing "Format", or by following the diskpart instructions at the page I got the original instructions from (linked to at the beginning of this post).

Open a command prompt as administrator. In Vista and 7, click start, type in cmd, then hold ctrl and shift while pressing enter (or right-click the cmd that appears in the search results and choose "Run as Administrator". In XP, you just need to be using an account with administrative privelages.

Navigate to the boot directory on your Windows 7 media:
cd E:\boot
(where E:\ is the mounted ISO or the DVD drive containing the Windows 7 disk)

Using bootsect, we’ll make the USB/SD media a bootable NTFS drive, ready for a Windows 7 image (my drive was labeled G):
bootsect /nt60 G:
If it gives an error about not being able to get a lock on the media, eject the media, maybe reboot the computer, and try again. If it returns "Access Denied", you're not running the command prompt as an administrator.

Step 3 – Copy the installation files from the Windows 7 disk or mounted ISO to the USB drive.
I like using xcopy to make sure I get everything:
xcopy e:\*.* g: /e /h
(again, my DVD or mounted ISO drive is e: and the USB/SD drive is g: in this example)

We're done with the command prompt now, so you can close the window or type Exit.

Step 4 – Begin installation on the Netbook
Plug in the USB/SD drive and turn on (or restart) the netbook
On start up press F12 to select the bootable drive (or if that option doesn't show up, press F2 to enter setup and turn on the option to allow F12 to show boot options).
Select the USB drive and press return
The netbook will boot from the USB drive, and prompt you to press any key to boot from cd or DVD. Press something (I like pressing enter or space) and setup will begin. From this point forward, if you see it prompt you like that again, do NOT press anything...you only want to boot from the DVD media at the beginning of the setup.

Step 5 - Installation
Now, if you want to install to the netbook and overwrite what's currently on your computer, you can proceed with the prompts as normal...it's pretty easy, even for a non-geek. (But I recommend doing a "Custom (advanced)" installation, NOT an upgrade installation). If that's the case, you can skip the rest of this post...congratulations!

However, if you want to dual-boot your computer using the VHD capabilities built into Windows 7, continue below:

When the Welcome to Windows 7 screen comes up with a button to "Install Now", press Shift+F10. A command prompt will open.

Type diskpart and press enter

Wait a minute for it to get to the diskpart> prompt. Now type:
create vdisk type=expandable maximum=80000 file=c:\Win7.vhd
to create a virtual hard disk file in your C:\ that can hold up to 80 GB, but will only be as large as you need (that is, it will start off as kilobytes, then expand the file as you add things to the virtual hard drive, up to a maximum of 80GB).

It should complete that very quickly. Now type:
select vdisk file=c:\Win7.vhd

Again, that should return immediately. Now type:
attach vdisk

When that's done, type exit, press enter, then type exit and press enter once more. The command line should be closed now. Go ahead and click the Install Now button in the Windows 7 installation routine. When it prompts you for what partition to install to, choose the 78GB (or so...it's not exactly 80GB) partition. It will warn you that Windows cannot be installed to this partition, but ignore that warning, it will work just fine, thank you very much.

Continue installation as normal.

Step 6: renaming the dual-boot options (useful if you have multiple Windows 7 VHDs installed, or if you are dual-booting with XP, which will be labeled only, "Previous version of Windows"). Totally optional...requires a higher level of geek.

Once you're in Windows 7 at the desktop, open up the command prompt as an administrator again. Type: bcdedit

It will list all your boot options. If you have XP as one of the boot options, you'll see one with {ntldr} as the identifier. If you want to rename that to something other than "Earlier version of Windows", (say, Windows XP) you can type in:
bcdedit /set {ntldr} description “Windows XP"

Otherwise, look for the identifier string for the option you want to rename. The one you're currently in will usually be {current}, while a different inactive Windows 7 or Vista installation might either be identified by {system} or by a really long string of random letters and numbers between curly brackets. DO NOT rename {bootmgr}...don't even touch this one. Once you've found the one you want to rename, use the same command as above, but replace {ntldr} with the identifier of the option you want to rename (including the curly brackets), and "Windows XP" with whatever you want the option to read (for instance, I've got "Windows 7 beta" and "Windows 7 RC" as two options on my computer).

Labels: , ,

Friday, March 27, 2009

Outlook Attachment Reminder - Home

I've been looking for something like this for a while...gotta give it a shot on a frozen computer to try it out.

Outlook Attachment Reminder - Home:
How often have you sent an email, probably [meaning] to send an attachment as well mentioning about it and after 5 minutes you get a reply saying there is no attachment attached!!

This project is to make sure you do not go through this ' self humiliation' often. Outlook Attachment Reminder is built to help you achieve this.

The logic is very simple, it searches for words like attachment, attached etc. (which of course you can manage) and if they exist, it checks if there are any files attached. If not, then it will prompt with a message box. Then you can add the attachment.

I'd always looked for a way to key a macro to launch using autocorrect or similar, so that as soon as I typed "attached" it would pop up the "browse" dialog for the attachment. Though this is probably a better method, as it doesn't make you do anything until you've hit "Send", so the attachment is sure to be ready by then.

The fact that the page reads a little bit like something that's been translated into english gives me pause, however.

Edit: See my post on June 2 for a more "official" tool that does the same thing, and doesn't make me as nervous as this one did.