Tuesday, December 11, 2007

Unable to setup Outlook 2003 after using 2007

After removing Outlook 2007 from all of the computers in our office, I ran into a few problems putting 2003 back on. When loading outlook, the error that the .ost file is not a valid folders file came up. So I decided to go into control panel, and head into the mail section to remove some profiles and re-add them. Upon trying to add an exchange server account the following message appeared: “There was an error locating one of the items needed to complete this operation. It might have been deleted” Sentinel had the answer, all you need to do is so a search for 'mapisvc.inf' on your C: drive. It will find 2 files, one in C:\Windows\System32, one in C:\Program Files\Common Files\System\MSMAPI\1033 I renamed both of them to mapiscv_old.inf - call it what you like, delete it if you are feeling game. Then run Outlook 2003, it will configure and put the file back there for you, and allow you to setup your account.

Tuesday, November 6, 2007

ASP.Net Cricket Web Part

Cricket season is rolling around, and where I work, we are mad cricket fans. Our office has two projectors setup in the office just to project cricket onto the walls while we are working (this year I've used a TV Tuner card in an old computer - and used Jetcast to transmit the channel audio to staff pc's. Last year, we also had the idea of getting Cricket Scores on our intranet homepage, at the time, the page was a simple html page, so I just created an IFrame to the Baggy Green desktop scorecard. This worked fine, except that there is over 60 staff, all sending requests to Baggy Green over and over. Now, we have moved to an ASP.Net web parts page as our frontpage, customizable by each individual user. So, I decided to make a web parts page for the cricket, I could just do the same thing as before, but I decided it was time to save some bandwidth, for both Baggy Green and our company. After some thought, my idea was this: Create a web part, which screen scrapes the desktop scorecard from Baggy Green, and saves the information in cache, and reloads it every minute. This would mean that only 1 person out of the 60 queries the page once a minute, rather than everyone potentially multiple times a minute. I also wanted to create a page that would allow anyone in the office to put in a URL to the match's scorecard, and it would set the frontpage going, rather than myself pulling out parts of the URL and entering in code. Here's my solution: Firstly, I have a page in which users submit the URL, and that URL gets searched using Regular Expressions for the Match ID which is displayed as a part of the GET variable string. This match ID is then stored in a database table I have setup for misc values (this could possibly be stored elsewhere, like in an XML file, I tried having it stored in cache for the duration of the match - however cache gets recycled/isn't reliable enough to count on it), with 2 columns, KeyName and KeyValue, which contained 'CricketMatch' and then the MatchID. The code for that section is as follows:
 Protected Sub Submit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
'inserts the ID of a match into the table.
'Use regex to find the id of the game.
Dim MatchID As String = MatchURL.Text
Dim r As Regex = New Regex("match", RegexOptions.None)
Dim m As Match = r.Match(MatchID)

Dim MatchLoc As Integer = m.Index

Dim ScoreBegin = MatchID.IndexOf("/", MatchLoc) + 1
Dim ScoreEnd = MatchID.IndexOf(".", ScoreBegin)
MatchID = MatchID.Substring(ScoreBegin, ScoreEnd - ScoreBegin)

'Inserting the CricketMatch key into PP_MiscValues table
' This gives the ID of the match for the score card to detect and use.

If Not MatchID = "None" Then
'Submit it to SQL Database, your SQL implementation may/will differ.
Dim _ibcon As SqlConnection = ibcon.ReturnConnection
_ibcon.Open()
Dim InfoBaseCommand As SqlCommand = New SqlCommand("Insert into PP_MiscValues (KeyName, KeyValue) Values _
('CricketMatch', '" & MatchID & "');", _ibcon)
Dim Result = InfoBaseCommand.ExecuteNonQuery
_ibcon.Close()

' Confirm to the user that the matchID is entered
Response.Write("Match with ID " & MatchID & " added, coverage has begun")
Else
Response.Write("No Match ID Found")
End If

End Sub
That is submitted from a text box with a submit button, I also have a delete button which removes any entry from that table, thus ending coverage. From there, I created a web part, which looks in the database and checks for a CricketMatch record in the MiscValues table, if there isn't any, it simply says 'no games are currently being covered', if there is one, then it checks to see if there is already cached code for the match, if there is, it simply displays it. If not, it then screenscrapes the page, and stores it in cache, with an expiry of 1 minute. The code for this is:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
'Check if a match is on, by checking for a MatchID in the database.
Dim MatchID
'SQL Connection to check if there is a CricketMatch record in the database
Dim _ibcon As SqlConnection = ibcon.ReturnConnection
Try
_ibcon.Open()
Dim InfoBaseCommand As SqlCommand = New SqlCommand("Select KeyValue from PP_MiscValues where KeyName _
= 'CricketMatch';", _ibcon)
Dim ResultReader As SqlDataReader = InfoBaseCommand.ExecuteReader
While ResultReader.Read
MatchID = ResultReader.Item("KeyValue")
End While
_ibcon.Close()


Catch ex As Exception
Response.Write(ex)
End Try

' If there is a record in the database, check the cache.
If Not MatchID Is Nothing Then

'Check if score is in cache
If Cache("CricketScore") Is Nothing Then
'create web client instance for scraping
Dim objWebClient As New WebClient()

'Scrape the page, getting the match ID from cache (idea is that you have another "admin" page to set this)
'Construct the URL of the desktop scorecard, using the MatchID
Dim strURL = "http://content-aus.cricinfo.com/australia/engine/current/match/" & _
MatchID & ".html?template=desktop;view=main;wrappertype=frame"
Dim aScrapedHTML() As Byte
aScrapedHTML = objWebClient.DownloadData(strURL)

'Convert the Byte array into a String
Dim objUTF8 As New UTF8Encoding()
Dim strScrapedHTML As String
strScrapedHTML = objUTF8.GetString(aScrapedHTML)

'Fix the bottom links on the desktop scorecard, they are relative, so they won't work anymore.
strScrapedHTML = Replace(strScrapedHTML, " ' Remove the close window link
strScrapedHTML = Replace(strScrapedHTML, " Close window", "")
'Replace the white text with black
strScrapedHTML = Replace(strScrapedHTML, "", "")

'If it worked, insert into cache, with an expiry of one minute, so only 1 computer per minute scrapes the page.
' Could lower this to 30 seconds if you want scores quicker
If Not strScrapedHTML Is Nothing Then
Cache.Insert("CricketScore", strScrapedHTML, Nothing, DateTime.Now.AddMinutes(1), TimeSpan.Zero)
End If

' Display cricket scores on page
lblHTMLOutput.Text = strScrapedHTML
Else
' If there was no value in cache,
'load the html from the cache & output it.
lblHTMLOutput.Text = Cache("CricketScore")
End If
Else
lblHTMLOutput.Text = "Currently no games are being played, this will be updated when one begins"
End If

End Sub
That then nicely displays the scorecard once a match is entered, and then doesn't display it when it's removed. Of course, this will get properly stress tested come match day, but from my preliminary testing

Wednesday, October 31, 2007

How to stop WDS 3.01 indexing via group policy

Microsoft recently pushed out what is an unwanted windows update for many: Windows Desktop Search version 3.01. I recently spent alot of my time removing this after I installed it on every computer along with Outlook 2007 , as it kept telling me I should install it to access full search functionality (it doesn't actually need it, you can still search the old way without it). My main reason for removing it was that it drastically slows down each users computer with indexing. All of our cad users were complaining to me that all of a sudden their computer decreased in speed, snoozing indexing fixed this (though it automatically starts again every restart), so I concluded it was time for it to go. Less than two weeks after removing it, I came in and received complaints once again - I was horrified to find that it had been reinstalled somehow. Some investigation revealed it was pushed out in a windows update - apparently accidentally - thanks Microsoft. Not wanting to uninstall them all again, not anytime soon anyway, I thought perhaps there was a group policy object to snooze indexing, or disable it all together, a google seemed to agree with me, so I set about finding the .ADM file. Turns out, in the latest version, it is located as part of the installer, to find it, you need to extract the installer, using the /extract switch, or winrar/7-zip. After extracting it, go to the 'update' folder, and 'desktopsearch30.adm' is the one you need. Snap it into your GP management, and away you go... well almost. Turns out, for some reason, Microsoft removed half of the group policy settings you can use in the latest version! 2.6 had all of them, but they were removed, God knows why, and this includes the option to disable it..Thanks again Microsoft! So what is there to do? How can you disable it? The answer is this, it's not the best option, but it will stop the stupid indexing(my kingdom for WINFS) from slowing down everyones computers!: In your Group Policy Object Editor on your imported WDS object - go to Computer Configuration -> Administrative Templates -> Windows Components -> Windows Search This will show you all of the settings you can change, the one you want to change is 'Stop Indexing on Limited Hard Drive Space', you can enable that, and set the MB limit to "2147483647" mb - unless your users have huge arrays of hard drives, I'm sure that they'll never have ~2147 terraybtes of hard drive space. Save that, and link it in, and when the group policy refreshes (you can force this by going to cmd and typing gpupdate /force) it should be set. If you don't know what I'm talking about with group policy - check here, for the guide on 2.6, it will help you up until "Under Administrative Templates, expand the Windows Desktop Search node." This is outdated now.

Tuesday, October 9, 2007

43 Exceptionally Useful AJAX applications

I stumbled across this great link today, 43 AJAX scripts to enhance your website. Check it out at Design Vitality

Thursday, October 4, 2007

Outlook 2007 custom forms - a black hole to avoid.

Microsoft changed a few things in Outlook 2007, including aesthetic features, rendering of emails, custom form creation, and other bits and pieces.

Firstly, aesthetically there are some menu changes, mainly in composing emails, Outlook is probably the worst example of the ribbon implementation in the whole of office, with it only partially implemented. It seemed somewhat unnecessary given that only email composition is affected by it, and that the cluttered menu of the main Outlook window remains (and some awful click counts when trying to access stuff like the manage forms menu - why isn't this in with the 'tools -> forms' menu?).

Then, despite kicking and screaming from anyone who sends HTML emails, they have changed the rendering of emails, from Internet Explorer to Word. It seemed somewhat silly given the release of Internet Explorer 7, but they've done it. It's added some cool Word-like features to editing of emails, and made copying and pasting from Word a breeze, but in the long run, you don't know what your emails are going to look like on the other users computer.

However this is not where I have had the most hassle, the company I work for recently purchased Office 2007 standard, seeing as we run an Windows SBS server, we already had Outlook 2003 licenses for all users, but seeing as we couldn't buy Office without Outlook we decided we might as well install it.

For a couple of years now, our company has been using Outlook 2003, with a Public Folder system for filing of all correspondence, despite Microsoft slowly prodding us towards Sharepoint, we can't see any reason too. As an engineering firm, all of our major documents and drawings are stored on a shared network drive, so they can be opened in Autocad. This works well for a company of around 60 employees. We just drag and drop our emails to the appropriate folder and thats that.

To simplify the filing process we have created a custom form, which has a field next to the subject field for our job number. This then sets the category of the email to be that job number, and carbon copies it to an account that will automatically file it. It's worked without glitch for a long time now. That is, until we installed Outlook 2007. It was claimed that even though there is a new way of doing form customization 'Form Regions', the old style will still work fine. It seemed to at first, emails still got filed correctly. However a number of problems started to occur.

Firstly, when trying to forward an email, that was received from someone externally (ie didn't use our custom form to create it), it causes the error "the messaging interface has returned an unknown error". We tried recreating the form from scratch, checking everything on the form, reinstalling Outlook etc - no luck.
Weirdly, on occasion it did magically work, but then it would stop again, and on any external email in the public folders it always did it.

Another major error, was that the custom form itself would randomly go really wide, or really small, and not scroll with text, see the pictures below for more details.

Really small:

Not as annoying as really wide, as the text wraps so its just like a small window with wasted space.


Most annoying of all - form goes really wide, the project id field is off the screen and you have to tab across or use the new set of scrollbars to get to it. If you type text that goes of the screen, it doesn't wrap, and doesn't automatically scroll across, so you can't see what you are typing.

These are the two biggest problems, and most common ones, other ones include
- Automatic signature insertion does not work anymore
- On some users outlook, attachments just disappear, even though you can still select save all attachments to get them, they do not show up on the view message screen.
- Can't rename emails in your inbox anymore, previously we could rename the subject of a message that was in our inbox, this made for easier filing.
- For some reason there is a rule setup automatically that removes the category from all emails.. why? This makes it harder to see what project internal emails are related to.
- Outlook:\\ links in IE no longer work - why?
- Can't get rid of the bar telling you to enable instant search - we don't want to, Windows Desktop Search on XP slows down Autocad to a crawl!
- Opening shared calendars is dodgey at best, sometimes works, sometimes doesn't.

The rest of the Office 2007 suite is going brilliantly, just some caution should be had for any small business looking to use Outlook 2007. Until a solution to every one of the problems mentioned above is found, our company will be sticking with Outlook 2003, which really doesn't offer much less in terms of functionality.

Wednesday, September 19, 2007

AjaxWindows! - A demonstration of what AJAX can do.

I stumbled across a very cool demonstration of the future of web applications. It's called ajaxWindows, and is a windows clone that you use in your browser. It has the layout that a windows user would be accustomed to, complete with recycling bin, my computer etc. It can sync the contents with your local computer, and store files in your gmail account! It uses ajaxWrite for writing office documents, and has a couple of other widgets and gadgets included. If you like that, it's not the only online operating system out there, have a look at this roundup of some more. With Silverlight, an ever expanding .Net framework, and all other technologies moving forward, the future is looking exciting.

Tuesday, September 18, 2007

The .adm file cpao12.adm is not in a valid format and must be replaced. Details: A string is expected at line 56.

The group policy templates for Office 2007 are a great help to system administrators, however upon installing them and setting the default template path for our workgroup – I received that error. (with the path to file before cpao12.adm)

A workaround courtesy of Felix on mcse.ms, edit cpao12.adm in notepad, and change every value of the following:

VALUEON !!L_true

VALUEOFF !!L_false

To

VALUEON NUMERIC 1
  

VALUEOFF NUMERIC 0

Do a replace all on that, and then while you are there, fix up outlk12.adm, changing:

KEYNAME Software\Policies\Microsoft\Office\12.0\Outlook\Security

VALUEON NUMERIC 1    

VALUEOFF NUMERIC 0    

VALUENAME PromoteErrorsAsWarnings    

EXPLAIN !!L_PromotingerrorsaswarningsExplain    

END POLICY

To

KEYNAME Software\Policies\Microsoft\Office\12.0\Outlook\Security

VALUENAME PromoteErrorsAsWarnings    

VALUEON NUMERIC 1    

VALUEOFF NUMERIC 0    

EXPLAIN !!L_PromotingerrorsaswarningsExplain    

END POLICY

There should be one instance of that (though there is a lot of outlook security keynames,
 so search for 'PromoteErrorsAsWarnings'. 

Tuesday, September 4, 2007

Office 2007 Customization Tool: APPEXTENSIONWARNINGS setting error

In my efforts to deploy office 2007 to my workplace, I used the Office 2007 Customization tool, which is available by running Setup.Exe (on the disk) with /admin switch applied.

I went through and spent alot of time considering each and every setting and selecting what I thought was best, then went to save my hard work and received this error:

I had no idea where this error came from, and a google search returned nothing.

So I experimented saving at regular intervals, and found that the error seems to be coming from the 'Office security settings' section, in the bottom box whenever I enabled 'Microsoft Office Excel - Application Add-ins warning options' it seems to crash. I just did not configure a setting from this and all seems to have gone well.

I'd say its a program bug, best to steer clear of that setting.

Monday, September 3, 2007

Deploying WSS 3.0 Web Parts easily to a production server with VSEWSS

There are a lot of pages on the internet which describe building and deploying Windows Sharepoint Services web parts. With the Visual Studio Extensions for Windows Sharepoint Services, creating a basic web parts is a breeze, it's a simple case of starting a new project from the web part template. Then by pressing f5 it creates the necessary files and deploys them. This is great for your development server, but what about when you want to deploy them to a remote server? It gets a little more complicated it would seem. I found a trick today that makes things a whole lot easier. The f5 button, creates a number of files in the \bin\Debug folder for the web part project, one of these is a script, which it uses for deploying the web part. Open this script, and find the section that says: set DefaultWebUrl=http://localhost/ set DefaultSiteUrl=http://localhost Change this to the site URL of your WSS deployment, and then copy all of the files in the bin\Debug folder over to that server, run the script, and it will open a command window outlaying the progress. Once it's completed, you should be able to open your WSS page and simply add the part to the page!

How to convert Flash EXE's to SWF files for embedding to web pages

I found a useful tool to convert flash EXE files (like the ones linked in my previous post), to SWF files, for easy embedding into HTML files. Northcode make a free tool, just run it, choose your exe file and it will save a SWF file in the same folder. To embed the file into a HTML page, rename the SWF file and add this code to your page:
<object height="400" width="600"> <param name="movie" value="FlashFile.swf"> <embed src="FlashFile.swf" height="400" width="600"></embed> </object>

Getting used to Office 2007 menus

The new Office 2007 interface is a major overhaul over previous versions, and in my opinion, it's great. It's designed to maximize productivity, and to reflect the changes in todays hardware, particularly that of the rise in popularity of widescreen monitors. It's designed to have the things related to what you are doing right NOW to be in front of you, just one click away, rather than having to go through the same 3 click process multiple times. Still, the biggest criticism I hear of it is that it is different, no one likes change at first, especially from a product that has stayed the same for over 10 years. Once you get used to the new interface, chances are you'll see the productivity gains, however at first, it can be a slow down. Here's a tool I found on Microsoft's website, aimed at helping with the transition. The guides to the 2007 office system interface, has flash files (and executable flash files for offline use) which show you an office 2003 menu, and let you click in it just as you used to, after selecting something, it will then show an animation of how to do this in office 2007. Neat! If after using that you still are fed up with the interface, there's always the add in tool, which gives you office 2003 menu in office 2007, however this isn't the ideal solution - as it costs money (has a time limited trial though if you wish to test it), and doesn't train you in the new changes, it just covers them up. My advice is to use the flash guides, and take the step, you'll see that it was worth it.

Friday, August 31, 2007

How to create a site programmatically in WSS 3.0

As part of a project I am working on, I need to make a lot of sharepoint websites based off the same customized template. I'm obviously not going to sit there and click over and over, so here's how to do it in C#, I hosted this in an ASPX page and ran it on the server. SPSite newSite = new SPSite("http://server/siteurl"); SPWeb newWeb = newSite.OpenWeb(); newWeb.AllowUnsafeUpdates = true ; newWeb.Update(); SPWebCollection subsites = newWeb.Webs; SPWeb newSubWeb = subsites.Add("siteurl", "sitetitle", "sitedescription", 1033, "template.stp", true, false); remember to add a reference to 'Windows SharePoint Services' and add 'using' lines for: using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; The AllowUnsafeUpdates part of the code allows you to do your method in the GET section of the code, for example Page_Load, I believe you might not need this if you do your work in a postback, ie by adding a button to click. To create a custom template, I simply created a website, customized it, and went to Site Actions -> Site Settings then under look and feel clicked "Save site as template". When you fill out that page it is important to take note of the filename you give it! As this is used in the code above. I called mine BWJob, so my template was BWJob.stp. If you forget this name, you can find it in the Site Template gallery. If you want to use a default template, refer to Todd Baginski's blog, he has a list of what to write in the template section. This information is also available in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\XML\WEBTEMP.XML - it follows the strucutre of "Template Name#Configuration ID" so Team Site is "STS#0" instead of "template.stp". This method worked well for me.

Wednesday, August 29, 2007

Usability: Don't interrogate your users when asking them to register

I saw a really good example of how to do an online registration form properly today. I'm talking about the form you fill out to register for a website, usually for discussion forums.

You might know the ones, you go to a forum to realize you have to register just to view it, and then you are bombarded with questions, only a few of which are compulsory.

For example, you might get asked for a username, email address and password - these are compulsory, but at the same time, there is input field after input field asking you for all of your personal details, birthday, interests, do you have a website, whats your msn/aim/icq/skype/xfire/insertIMProgramhere - it's okay though, you don't have to put these in.

These types of sites annoy me, I, like most users, like things done quickly and pain free, it's annoying enough that you made me sign up to your website and then get a verification email from my inbox just to see if there is any active discussion, don't make things worse by making me look from text box to text box seeing if there is a * character next to it. I want to do the minimum amount of thinking, I'm not going to surrender my life story to you if I don't even know what the forums are like!

Sure, maybe later on, when I've decided to actively participate in your community, then I'll go to edit my profile and add in some details I'd like to share. But in the mean time, just show me what I need to do - make me think well maybe this isn't so much of a hassle after all, rather than dammit do I have to put all that in?

Here is the example of what I was talking about, well done Babstats.com:



Tuesday, August 28, 2007

How to post HTML and other code on Blogger

On creating my last post, I encountered a problem - the code I put in the editor was dissapearing, or at least half of it was! I figured this was due to it being read as HTML code, and found from THIS blog post, that you need to use HTML entities instead of normal html tags. I didn't feel too much liek going through my document and changing every tag, so I went searching and found THIS, on the W3C site. You enter HTML code, it converts it to HTML entities ready for posting, easy!

Monday, August 27, 2007

An online solution for viewing DWF files, with capability to drag into Autocad

On the Autodesk Forums, I recently enquired about a way of replacing WHIP! for autocad, which allowed us to have an intranet with standard details for our cad users to open up, view, and if needed drag and drop into autocad.

When Autodesk discontinued WHIP! they replaced it with DWF Viewer, and more recently have released Autodesk Design Review.

After much playing around I developed the solution you see in the image (I've zoomed out on the drawing).

Our intranet had a javascript function for opening DWF's in a certain sized window, called dwfwin, I edited that to open an ASP.Net page with the address of the drawing in the querystring.

From then, I filled out the code for the Design Review embedded drawing, using the value passed in the querystring.

Here is the code I used:

<% Dim dwf
dwf = Request.QueryString("dwf")

Dim dwfxml

dwfxml = Split(dwf, "/")
Dim arraymax
arraymax = UBound(dwfxml)

dwfxml = Left(dwfxml(arraymax), Len(dwfxml(arraymax)) - 4)
dwfxml = "http://bwonline/dwf/xml/"& dwfxml & ".xml"
'response.write (dwfxml)
%>

CODEBASE=http://www.autodesk.com/global/dwfviewer/installer/DwfViewerSetup.cab#version=7,0,0,928
WIDTH="97%" HEIGHT="94%">

">
That worked fine for viewing drawings, though it was slower than our old WHIP! solution, due to the extra features it has, but it's not a big issue for us. Another problem was though, that it couldn't drag and drop the drawing into Autocad - which was the main point of the exercise. For this, we used I-Drop.

The idea behind I-Drop is that you make a picture of the drawing file, and that picture has an XML file behind it that tells the site where the .DWG file is that Autocad will import when that image is dragged and dropped. However I wasn't going to go through and make images of all our drawings, and we didn't need them wasting extra space so I came up with the idea of making the image a small 'D' (for drag/drop), and as you can see from the image above, that's what happened.

To do this, I needed to generate the XML file, as I wasn't going to go through and make them for each individual one, so I created some code to do it for me, using the System.XML Namespace. There is a certain layout you need to use for the I-Drop XML file, it needs to look like this:

<?xml version="1.0"?>
<package xmlns="x-schema:idrop-schema.xdr">
<proxy defaultsrc="d.jpg" />
<dataset defaultsrc="L:/acad/acad_str/drg-exs/1-9.dwg" />
</package>


The values that change are the d.jpg is the image used, and the .dwg file is the location of the drawing file. This was easy for me to generate automatically as the DWF's and DWG's are kept in the same folder on our network.


To generate this file, I added this code to the Page_Load sub of my aspx page.

'Construct xml file name from dwf input string
Dim dwf
dwf = Request.QueryString("dwf")
Dim dwfxml
Dim dwfdwg
dwfxml = Split(dwf, "/")
Dim arraymax
arraymax = UBound(dwfxml)

dwfxml = Left(dwfxml(arraymax), Len(dwfxml(arraymax)) - 4)

dwfxml = "D:\Inetpub\intranet\bwo2\dwf\xml\" & dwfxml & ".xml"
dwfdwg = Left(dwf, Len(dwf) - 1) & "g"

'check if it has already been written
If Not File.Exists(dwfxml) Then
'Write xml file

Dim xmlNewDocument As XmlDocument = New XmlDocument
Dim sb As StringBuilder = New StringBuilder
sb.Append("")
sb.Append("")
sb.Append("")
sb.Append("")
sb.Append("")

xmlNewDocument.LoadXml(sb.ToString())

xmlNewDocument.Save(dwfxml)

End If


Basically this works out what the name of the .xml file will be from the querystring inputted, in my case I made it the name of the .dwf file, but with the extension changed.

These XML files only need to be made once so I kept them all in the one spot, and made my code check if one was made, if not, it created it, so there would be a slightly longer load the first time - but then that would never happen again.

Then later on, in the body of my page just after the design review object I used:
<object name="idrop" classid="clsid:21E0CB95-1198-4945-A3D2-4BF804295F78" width="15" height="15">
<param name="background" value="background.jpg">
<param name="proxyrect" value="0,0, 15,15">
<param name="griprect" value="0, 0, 15, 15">
<param name="package" value="<% =dwfxml %>"/>
<param name="validate" value="1">
<embed width="15" height="15" background="background.jpg" proxyrect="0,0, 15,15"
griprect="0, 0, 15, 15" package="<% =dwfxml %>" validate="1" src="background.jpg" name="idrop">
</embed>
</object>

With dwfxml variable being the generated name and location of the xml file.

A point to note is that IE7 has security on objects like these, where you will need to click once to turn on the object, and again to use it. But that's not much of a big deal.

So the user simply reviews the drawing, then when they wish to, they click and drag the D character into Autocad. All staff need the I-Drop plugin, and Design Review, so I have linked to those on the page if anything doesn't show up properly. Problem solved! All seems to work well!

Friday, August 24, 2007

Disabling Internet Explorers advanced security configuration

I came across this problem today, in server 2003 I couldn't click 'OK' on my own sharepoint page, I figured this was because of the enhanced security. To remove it, go to control panel, add remove programs, change to windows components, and 'Internet Explorer Enhanced security configuration' is a component, deselect it, and click next. It should disable it, then when you fire up internet explorer you should see:
Caution: Internet Explorer Enhanced Security Configuration is not enabled
Perfect! Problem solved, I can click OK now! My pages load faster as well.

Free OCR Program

I required an OCR scan on a peice of paper we had lost the electronic copy for today. Most OCR software is pretty expensive, and all have varying results. There didn't seem to be a windows open source solution on sourceforge so I had a look for freeware, expecting to get something with a 30 day trial that writes TRIAL TRIAL GIVE ME MONEY all over your document, however I was surpised to find Simple OCR, seems to be completely free. To scan my document, I used the scan to JPEG feature on our Canon 3170 photocopier, which splits each page up into a JPEG file and sends to my email, I saved these to a folder. I then opened Simple OCR, did a machine print read, added all of the JPEGS (hold down shift and add all of them), ok'ed the preview, then clicked convert to text, it did it's thing then split my screen into two and showed me everything it wasn't sure about - neat, makes up for it's downfalls by admitting them. I went through, much like Microsoft Word's spell check, and it highlights the original word in the image, and it's translation. A few errors, but it's better than typing out the whole thing - or paying lots of money! Then it was a matter of saving it as a word document, and fixing up the formatting.

Wednesday, July 25, 2007

Using Excel documents as a data source in ASP.Net

This is something that I mentioned last blog, finally I've gotten around to posting it, on a side note, I'm also trying out the new 'blogging' feature in Word 2007, go to the office button, click new, and start a new blog post, it'll run through setting it up, and then away you go.. hopefully it works!

The scenario I had, was that we have a spreadsheet setup for collecting payments for the 'bar tab' we have for our social committee, who sell chocolates, chips, beer etc at a low cost. This is tallied up on a spreadsheet, and an email is sent around with amounts. I thought it would be good to have this data on each individual users intranet homepage. So I set about making a web part for it.

We didn't want to change the spreadsheet to an ASP form, as it was working fine as it is, and I didn't have the time to code one and teach the social committee treasurer how to use it. and I didn't have the time to code one and teach the social committee treasurer how to use it. So I thought, surely there is a way to extract the data out of an excel spreadsheet, and sure enough there is.

First off, I setup my cache as mentioned in my previous post 'using cache to determine a time for content reloading' so it only queries the excel spreadsheet once every 12 hours, so if the cache is still there, it doesn't get the new data, if not then it gets new data and adds something to cache. I decided that instead of having the data in cache, which could be deleted by IIS, and would require regular expressions to query properly, I would store it in a SQL table. So effectively I was synchronizing a couple of columns out of an excel spreadsheet with a SQL table.

I setup my SQL table, and then set about talking to the excel sheet. I stored it under the a folder on the server, and just gave the social committee people permissions to access and edit it – which probably isn't the most secure approach, but it was fine for what I am doing, and fairly idiot proof.

To talk to the table, you set up an 'OleDbConnection', I setup mine as follows:

Dim DBConnection = New OleDbConnection( _

"Provider=Microsoft.Jet.OLEDB.4.0;" & _

"Data Source=" & Server.MapPath("~/SocCom/collection.xls") & ";" & _

"Extended Properties=""Excel 8.0;HDR=Yes""")

There I've got my data source as a mapped path to the xls file, and had its properties as an excel file. It connects using the Microsoft jet engine – similar to Access.

From then, I added a Try/Catch statement to catch errors which occur when someone is editing the file while it is trying to be accessed.

Try

DBConnection.Open()

Dim SQLString As String = "SELECT [Name], [Balance] FROM [Collection Summary$] WHERE [Name] is not null and [Balance] is not null"

Dim DBCommand = New OleDbCommand(SQLString, DBConnection)

Dim DBReader As Data.IDataReader = DBCommand.ExecuteReader()

There I've opened the connection, and selected the columns with 'Name' and 'Balance' in the topmost cell – they need to be enclosed in square brackets. The From part of the SQL statement has [Collection Summary$] as that is the sheet name, the $ sign is required at the end (though my sheet name is only 'Collection Summary').

Also take note that I have added a where statement that does not show Null values of each column, this is important, as if you do not do this, then it will take more than 5 seconds to do the query, and will return a whole heap of null values, as it queries all the values in the spreadsheet, null cell or not.

That will return like a normal SQL query, you could bind it to a data grid, or whatever you like, in my case, I first deleted all the old values from my SQL table (I could have updated them – however employees leave and join, and spelling mistakes are corrected etc, so its better just to start a fresh each time) then did a 'While DBReader.Read' to loop through the values, writing them to variables, and inserting each to the database as it went.

At the end of that loop, I closed the DBReader, and DBConnection. Then added my catch statement:

Catch ex As System.Data.OleDb.OleDbException

Finally End Try

ReadFromDB()

The exception was the System.Data.OleDB.OleDbException – which I tested was when the spreadsheet was already in use. As you can see I did nothing on the event of an error – as it doesn't matter if you can't read the data, I just didn't want the page to spit out an error – I wanted it to continue, which it does, and goes to the next line of code which is a call to my 'ReadFromDB()' sub procedure, which queries the database to get the data from the SQL table. So if there is an error, it goes to the ReadFromDB Sub, if not, it still goes there.

It then reads from that and prints my data. Done!

Edit: As a side note on my blogging with Word experiment, it worked great, however the formatted text I copied from Visual Studio 2005 added extra spaces, which is because it shows up as huge text in my editing menu, so each line break is size 72 or whatever it is. Other than that, worked brilliantly and was very easy.

Saturday, July 7, 2007

ASP.Net: Using cache to determine a time for content reloading (rather than reading data from cache)

I have been experimenting with this recently, ASP.Net has a good, simple, quick caching model. Cache.Insert("PageReloadTimer", "Yes", Nothing, Datetime.Now.Addminutes(5), Timespan.Zero) will give you a cache of the word "Yes", named PageReloadtimer, with no dependencies, for 5 minutes until it is deleted. Caching is of course great for optimizing performance, as you can cache data instead of getting it from the source, which is great for screen scrapes and other data feeds. However, it could also be used as a simple timer, I'm sure there are other ways to do this, but this seems simple enough (comments are appreciated though). The scenario I had, is on my companies local intranet, we want to display data from an excel file, as you will see in my next post, excel files can be used in ASP.net as a datasource, just as if it were an SQL database. However the performance is obviously reduced (if you don't use a where statement pages take a very long time to load - so a where statement is essential, even if it just eliminates nulls). I decided we would like this to be stored in our SQL database, for easy querying, and so it will be backed up, as it was financial data. So I made the page query the excel sheet, then insert all of the data into our SQL database, I decided this only needs to be done every say, 12 hours, so, to tell it to do this I simply did a Cache.Insert("PageReloadTimer", "Yes", Nothering, Datetime.Now.Addhours(12), Timespan.zero) then added an if statement to the start of the excel query, If Not Cache("PageReloadTimer") is nothing then..... This skips the excel loading, and goes straight to reading the data from the SQL database. Works perfectly. I could even change the "Yes" which doesnt really mean anything, to a timestamp of when it was updated, allowing me to add "this information was last updated on ..." to the page. I could of course, have cached all the actual data, and used regular expressions to query it, but that wouldn't have given me the advantages of an SQL database, and would have been extra unnecessary coding. You can read more on caching at 4 Guys from Rolla, and OnDotnet.

Tuesday, June 5, 2007

Wireless Keyboards / Mice

I'm unsure of the state of the more expensive wireless keyboards, but I had my first brush with the technology recently. I needed a USB keyboard for my laptop, so I decided to upgrade the old HP ps2 keyboard that had served me well. A trip down to dick smith revealed that the standard of most low range keyboards was not as I would have thought the years of technology advances would bring. I had used cheap USB keyboards on the other computers in the house - and hate them, the keys advertised as 'soft' annoyed me, and seemed to stimulate RSI. I much prefer the easier to press, but 'harder' feel that Microsoft offer in their multimedia keyboards. Alas dick smith did not have any of this type, instead stocking mainly Logitech, who subscribe to the 'soft' theory. Finally I found one I liked, alas, $60, so much for my $20-30 dollar budget (who wants to pay lots for a keyboard?, it's not like its an all that complex piece of equipment). Why so much? It's cordless, and comes with a mouse. Hmm, I hadn't been too keen on cordless, but what the heck, I need it today. I bought it, brought it home, and was at first excited by the thought of my chord not bumping my yellow pages monitor props (pretty much gathered I'm cheap yet?). After using it for a small while, I quickly realized, that it wasn't going to keep up with my typing. There was a delay from the end of a sentence, to when it was typed out on screen. Is this the case on all keyboards, even the more expensive range? I don't know, perhaps bluetooth are better? But for now, my advice is to stay away from the cheaper ones. I took it back, after trying to get used to it, and am now sitting on my trusty PS2 keyboard again, until I can track down the Microsoft version (they make great hardware, despite their software 'reputation').

Synergy - Open Source program similar to KVM switch

Ok, so maybe not exactly like a KVM switch, but good enough for me! So here's the situation, I have a laptop which I take to work and uni, it's sitting next to my dual 19" LCD monitors connected to my main computer. My laptop is VPN'ed into work, so I can keep an eye on emails while I do some uni work on my main PC. I get an email which requires my attention, so then I have to move all the way over to the laptop, and use it's keyboard and mouse. A pain, but I don't want to fork out for a switch to swap control over. I need to no longer! Thanks to a great open source program, Synergy. Install it on both computers (even works across platforms!), and set one up with two 'screens', named using the computer names, and then set up 2 links (one to go from your main computer to laptop, and then visa versa) Then fire it up on your laptop, tell it the hostname to connect to (this didn't work for me - but IP address did) and away you go. Very cool, and saved me alot of time!