Mike Borozdin's Blog

A blog about programming, web and IT in general

Search

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© 2009 Mike Borozdin

PHPExcel: Manipulate Excel Spreadsheets with PHP on Linux

Have you ever faced a situation when you need to manipulate Excel spreadsheets with PHP on the server that is running Linux? If you had a Windows Server you could use PHP COM extensions. However they are unavailable on Linux.


Hopefully, there is a solution. It is called Open XML. It’s a new format of Microsoft Office documents introduced in Microsoft Office 2007. Basically, an Open XML file is a ZIP archive that contains XML files that represent the document mark-up. You can view it yourself or read some documentation, my article isn’t about Open XML, but about the PHP library for working with Excel 2007 files. It also supports Excel 97 format by incorporating a PEAR library.


The library is called PHPExcel. It allows you to read/write Excel spreadsheets, save them in many formats including PDF and HTML. It supports formulas,styles and etc.

It requires:

  • PHP 5.2+
  • GD extension
  • XML extension
  • ZIP extension


I have these two simple examples that show you how to create an Excel spreadsheet and save it in several formats and how to read a spreadsheet and display it on the HTML page.

Writing:

<?php

//Here we set the include path and load the librarires
set_include_path(get_include_path() . PATH_SEPARATOR . '../PhpExcel2007/Classes/');
require_once('PHPExcel.php');
require_once('PHPExcel/IOFactory.php');

$excel = new PHPExcel();
$excel->setActiveSheetIndex(0); //we are selecting a worksheet
$excel->getActiveSheet()->setTitle('Products'); //renaming it

//here we fill in the header row
$excel->getActiveSheet()->setCellValue('A1', 'Title');
$excel->getActiveSheet()->setCellValue('B1', 'Price');
$excel->getActiveSheet()->setCellValue('C1', 'Quanity');
$excel->getActiveSheet()->setCellValue('D1', 'Total price');

//here we put some values
$excel->getActiveSheet()->setCellValue('A2', 'Fictional TV set');
$excel->getActiveSheet()->setCellValue('B2', 300);
$excel->getActiveSheet()->setCellValue('C2', 1500);
$excel->getActiveSheet()->setCellValue('D2', '=B2*C2'); //this is how we put formulas, just like using Excel

$excel->getActiveSheet()->setCellValue('A3', 'Fictional mobile phone');
$excel->getActiveSheet()->setCellValue('B3', 200);
$excel->getActiveSheet()->setCellValue('C3', 5000);
$excel->getActiveSheet()->setCellValue('D3', '=B3*C3');

$excel->getActiveSheet()->setCellValue('A4', 'Fictional laptop');
$excel->getActiveSheet()->setCellValue('B4', 1000);
$excel->getActiveSheet()->setCellValue('C4', 2000);
$excel->getActiveSheet()->setCellValue('D4', '=B4*C4');

//some summarizing formulas
$excel->getActiveSheet()->setCellValue('C5', '=SUM(C2:C4)');
$excel->getActiveSheet()->setCellValue('D5', '=SUM(D2:D4)');

//Now we save the created document in the Exce 2007 format
$excelWriter = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
$excelWriter->save('Products.xlsx');

//in PDF
$pdfWriter = PHPExcel_IOFactory::createWriter($excel, 'PDF');
$pdfWriter->save('Products.pdf');

//in HTML
$htmlWriter = PHPExcel_IOFactory::createWriter($excel, 'HTML');
$htmlWriter->save('Products.html');

//and in the old binary format
$excelBinaryWriter = PHPExcel_IOFactory::createWriter($excel, 'Excel5');
$excelBinaryWriter->save('Products.xls');

?>

 

Reading:

<?php

//Here we set the include path and load the librarires
set_include_path(get_include_path() . PATH_SEPARATOR . '../PhpExcel2007/Classes/');
require_once('PHPExcel.php');
require_once('PHPExcel/IOFactory.php');

$excelReader = PHPExcel_IOFactory::createReader('Excel2007'); //we instantiate a reader object
$excel = $excelReader->load('Products.xlsx'); //and load the document

print('<table border="1">');
for ($i = 2; $i < 5; $i++) {
    print('<tr>');
   
    print('<td>');
    print($excel->getActiveSheet()->getCell('A' . $i)->getValue()); //this is how we get a simple value
    print('</td>');
   
    print('<td>');
    print($excel->getActiveSheet()->getCell('B' . $i)->getValue());
    print('</td>');
   
    print('<td>');
    print($excel->getActiveSheet()->getCell('C' . $i)->getValue());
    print('</td>');
   
    print('<td>');
    print($excel->getActiveSheet()->getCell('D' . $i)->getCalculatedValue()); //this is how we get a calculated value
    print('</td>');
   
    print('</tr>');
}

print('<tr><td>&nbsp;</td><td>&nbsp;</td>');
print('<td>' . $excel->getActiveSheet()->getCell('C5')->getCalculatedValue() . '</td>');
print('<td>' . $excel->getActiveSheet()->getCell('D5')->getCalculatedValue() . '</td></tr>');
print('</table>');

?>

 

Conclusion

PHPExcel is a very poweful library which is easy and well documentated. Of course you can use it not only on Linux, but on any operating system, including Windows.


Posted by Mike Borozdin on Monday, June 30, 2008 10:20 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (4) | Post RSSRSS comment feed

In Search Of The Perfect UI

Do you remember your first experience of using a computer? It doesn’t matter whether it was DOS with Norton Commander or Windows. Anyway you had to learn how to find the necessary applications, how to execute them, once again it doesn’t matter whether you clicked on the folders and files on the blue background or used the Start menu. It’s important that you learnt the definitions or metaphors; you learnt that icon is an application or something else; you learnt that you have to click twice on it to open it and so on.


Having got used to those metaphors, we easily use a computer unless we face an application with a non-standard interface that confuses us because we have to learn again.


The same thing applies to web sites as well, if a website has a non-standard navigaton it confuses us, even though its navigation is convenient, but not standard.


As a result the developers have to create user interfaces within the standard paradigm, it is right though, because we don’t have to learn everytime we run a new application. So we can divide all the UI’s into two types:

  • Standard
  • Bad


That is a problem in fact - we cannot go beyond the limits of the paradigm, because user interfaces are created by the people who are used to the standard paradigm. But the fact that we are used to something doesn’t mean that it’s the best thing ever, we just haven’t seen a better thing probably.


These things stroke my mind when I heard a dialogue in a computer store between two girls who were looking for a portable music player and a salesman. They got frustrated when the salesman told them that they needed a program to upload music to the player. Even though the program is shipped with the player they were still confused. They just didn’t understand that, but that was clear for me, it was clear for the salesman because we were used to the fact that we needed an application to upload music to the player. But those girls didn’t think within that paradigm.


That is why it’s worth goin beyond the standards of the created paradigm. I think it’s worth doing that, simply because it will help us to learn new ways of creating UI. Probably it’s worth consulting with complete newbies who can offer something new – a better way of interaction between people and computers.


Tags:
Posted by Mike Borozdin on Saturday, June 28, 2008 12:53 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

Getting BlogEngine.NET To Work With The Local Time Zones: Part II (in case JavaScript is disabled)

In the article called "Getting BlogEngine.NET To Work With The Local Time Zones" I described how to convert the times of the posts to the local time zones of users relying solely on JavaScript. However I got a complaint that if JavaScript is disabled for some reasons, then no date and time are displayed.


It can be fixed, I’ll explain how, but in this case – if JavaScript is disabled, the time will be in GMT, so just put the following code to PostView.ascx that basically outputs the time in GMT and if JavaScript is enabled it replaces a GMT time with a local time.

<span id="postDate_<%=Post.Id %>" class="pubDate"> on
    <%=Post.DateCreated.ToLongDateString() + " " + Post.DateCreated.ToShortTimeString() %> GMT
</span>
<script type="text/javascript">
    $("postDate_<%=Post.Id %>").firstChild.nodeValue = "on " + ConvertToLocalDate('<%=Post.DateCreated.ToLongDateString() + " " + Post.DateCreated.ToShortTimeString() %>');
</script>

Posted by Mike Borozdin on Friday, June 27, 2008 10:26 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

LINQ To MySQL

LINQ to SQL is a great tool that saves a lot of time. However it has one disadvantage – it supports only SQL Server. Anyway it’s possible to write your own LINQ provider. Sure, there is one for MySQL. It is called DbLinq, in fact in supports many databases:

  • MySQL
  • Oracle
  • PostreSql
  • Ingress
  • SqlLite
It’s not finished yet, however you can still try to use it. I’m going to explain how to use it in this article; we’ll go through 3 steps:
  1. Installation
  2. Using DbLinq in a console application
  3. Using DbLinq in a ASP.NET application

Installation

  1. Go here and download the ZIP archieve
  2. Unpack the archive
  3. Open the Visual Studio solution - DbLinq
  4. Build the solution

Using DbLinq in a console application

Ok, let’s try it in action, we are going to create a console application that will retrieve, insert, update and delete records from the database.

First, we need to generate the data context and the table classes. Unfortunately you cannot do this in Visual Studio, but there is a command line utility called DbMetal and its visual analogue – Visual Metal that is written in WPF, by the way.


Go to the \dblinq2007\DbMetal\ folder, there are several BAT files, open in your favourite text editor run_myMetal.bat, since we are dealing with MySQL, and change the necessary parameters, save and run it. You must have got a generated CS file, copy it to your console application project.
Then, it’s time to add the references, you should add the following:

  • System.Data.Linq
  • DbLinq.dll (located in \dblinq2007\DbLinq.MySql\bin\release\)
  • DbLinq.MySql.dll (located in \dblinq2007\DbLinq.MySql\bin\release\)
  • MySql.Data.dll (located in \dblinq2007\lib\)

Since the table is called Products, I want the class that represents a stored entity to be called Product, not Products, as it was called by DbMetal. So, I change the generated code.


Compile the project to check if there are no errors. If you get any error, check if there are all the necessary references.


Let’s write some code; basically we want just to display the data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient; //Don't forget to add this line

namespace MySqlLinqTest
{
    class Program
    {
        static void Main(string[] args)
        {
            LinqTest db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));

            var products = from p in db.Products
                           where p.Category == "Sport cars"
                           select p;

            foreach (var product in products)
            {
                Console.WriteLine(product.Name);
            }
        }
    }
}

That works. What about inserting a new record? No problems!

db.Products.InsertOnSubmit(new Product { Name = "Some car", Category = "Some category" });
db.SubmitChanges();

var products = from p in db.Products
               orderby p.Name
               select p; 

foreach (var product in products)
{
    Console.WriteLine(product.Name);
}

Ok, let’s remove the newly added record:

Product someCar = (from p in db.Products
                      where p.Name == "Some car"
                      select p).First();

db.Products.DeleteOnSubmit(someCar);
db.SubmitChanges();

Let’s update something:

Product bentley = (from p in db.Products
                   where p.Name == "Bentley"
                   select p).First();

bentley.Name = "Bentley Continental";
db.SubmitChanges();

Using DbLinq in an ASP.NET application

It was funny enough, but the console applications are not very useful when dealing with the database, let’s write something that is closer to a real world – an ASP.NET application.


Create a C# web site; copy the generated file we used in the previous example.


Don’t forget to add the necessary references.


We are going to add a GridView and bind the data retrieved from the database.

Default.aspx

<asp:GridView ID="gridProducts" runat="server">
</asp:GridView>

 

Default.aspx.cs 

protected void Page_Load(object sender, EventArgs e)
{
    LinqTest db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));

    gridProducts.DataSource = from p in db.Products
                              orderby p.Name
                              select p;
    gridProducts.DataBind();
}

It works.

What about LinqDataSource, can we use it with DbLinq? Yes, we can, but it’s a bit tricky. If we add a LinqDataSource, we’ll get an error saying that there’s no parametless constructor in our DataContext. That is a thing that hopefully will be fixed in the new versions, but now we have to write a wrapper around a generated DataContext.

App_Code/Products.cs

public class MyDataContext
{
    private LinqTest _db;

    public MyDataContext()
    {
        _db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));
    }

    public Table<Product> Products { get { return _db.GetTable<Product>(); } }
}

Then, we can use LinqDataSource as usual:

<asp:LinqDataSource ID="dsProducts" runat="server" ContextTypeName="MysqlLinqTest.MyDataContext"
    TableName="Products">
</asp:LinqDataSource>

<asp:GridView ID="gridProducts" runat="server" DataSourceID="dsProducts"> 
</asp:GridView>

Conclusion

As you see you can use LINQ to work with MySQL, unfortunately sometimes it’s not very convenient and we have to wait for the new versions or wait for a LINQ to MySQL provider from MySQL.
 


Posted by Mike Borozdin on Thursday, June 26, 2008 3:30 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (6) | Post RSSRSS comment feed

Users Never Read Manuals

I was in the store the other day paying for my mobile phone. There was a middle-aged woman in front of me who was trying to pay for her mobile phone with the payment machine. This payment machine was recently installed, so it was difficult for some people to get used to it. Even I saw the machine for the first time. Anyway that woman was nervously trying to pay, however she even couldn’t go further than entering her phone number, since I hadn’t any experience with that machine as well, I advised her to read the manual that was under the button in the bottom of the screen. She got angry when she heard my advice. Then I noticed that she just didn’t fill in the region code, I told her about that, she didn’t listen, got angry and went away.

That was a good example of the "paradox of the active user" stating that users never read manuals, instead they just start using the thing (software or hardware) immediately.  Even though they are having problems with that thing they still refuse to read any manuals.

That’s the important thing that should be kept in mind when desiging any kind of user interfaces, from a desktop application to a website.  The UI must be self explanatory; there shouldn’t be any need for reading manuals.

Tags:
Posted by Mike Borozdin on Tuesday, June 24, 2008 8:46 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (5) | Post RSSRSS comment feed

A Practical Example Of Using The New Features Of ASP.NET 3.5

This tutorial doesn’t cover the theoretical basics of the new features and controls, instead it concentrates on the practical example of using the new features. This tutorial covers the following features:

  • LINQ (Language Integrated Query) for the data manipulations
  • ListView control for presenting the data
  • LinqDataSource for binding data
  • DataPager for pagination
  • ASP.NET AJAX for getting rid of the unncecesassary page reloads

Requirements:

  • Visual Studio 2008
  • SQL Server

Project

Our project is quite simply, it's just a guestbook, but it's good for demonstrating the cool features of ASP.NET 3.5 and .NET 3.5 in action.




 

So, just open Visual Studio and create a new C# website.

Database design
We need to create a database when the comments will be stored. We’ll just create a database with a single table that will keep the comments posted by the authors. We can create it in Server Explorer without leaving Visual Studio.

 



Don’t forget to set the Id field as an identity.
Let’s populate the database as well, so that we’ll have some data to display, just execute these queries:

INSERT INTO Comments
(Author, Text)
VALUES('John', 'ASP.NET 3.5 rocks!');

INSERT INTO Comments
(Author, Text)
VALUES('Mary', 'ASP.NET 3.5 is so cool!');
 

LINQ

Then, we need to create a LINQ To SQL class that will be using for the data manipulations (retrieving and inserting). We open Website->Add New Item and choose LINQ To SQL Classes

 




Then we open Server Explorer and drag and drop our table on the workspace.
 


Now we just save this file and go futher, we can view the generated code though located in App_Code\Comments.dbml\Comments.designer.cs

LinqDataSource

Ok, it’s a time for create your webform that will hold all the content. Actually, it is already created by Visual Studio, we just have to add some content there.
We are going to start with a data source, open Toolbox, expand the data section and find LinqDataSource there. 

 



Drag it to the webform.  You will get the following code:

<asp:LinqDataSource ID="LinqDataSource1" runat="server">
</asp:LinqDataSource>


Give it a more appopriate name, something like dsComments. Now switch to the Design view, click on the LinqDataSource we’ve just added and select Configure Data Source.

 



Choose the only avaliable data context object and click Next.


 
Then leave everything by default by click on the Order By button. And choose Id and the Descending order.


 
Click Ok and finish, switch to the Source view and look at the code we get:

<asp:LinqDataSource ID="dsComments" runat="server"
    ContextTypeName="CommentsDataContext" EnableInsert="True" OrderBy="Id desc"
    TableName="Comments">
</asp:LinqDataSource>

 

Pretty simple, I would say.

ListView

It’s time to add the ListView control. It’s a new data bound control that enables you to have a full control of the rendered HTML code. It’s also located in the Data section of Toolbox. Drag it and rename it to lvComments, also don’t forget to assign a data source to it. You must get the following code:

<asp:ListView ID="lvComments" runat="server" DataSourceID="dsComments">
</asp:ListView>


Then, we have to add the <LayoutTemplate> that will be the root template

<asp:ListView ID="lvComments" runat="server" DataSourceID="dsComments">
    <LayoutTemplate>
        <h1>ASP.NET Guestbook</h1>
        <div id="itemPlaceholder" runat="server"></div>
    </LayoutTemplate>
</asp:ListView>

 

Please, note the we have the div tag with id="itemPlaceholder" runat="server". They denote that ListView content will be placed in the place of that div, itemPlaceholder is the default ID of the content placeholder.

To display out data we should add the <ItemTemplate> element and place some content there

<ItemTemplate>
    <div>
        <b><%# Eval("Author") %></b> says<br />
        <%# Eval("Text") %>
    </div>
</ItemTemplate>


It’s simply and has nothing new if you worked with other data bound controls. Let’s add the separator element to separate the posts:

<ItemSeparatorTemplate>
    <hr />
</ItemSeparatorTemplate> 


Compile the website, you should you see a very simply webpage with just two comments by Mary and John that we added in the very beginning. It’s cool, but what about enabling users to post comments? It also can be done by using LinqDataSource and ListView.

First, add EnableInsert=”True” attribute to the LinqDataSource. Second, we need to add the insert item template to the ListView.

<InsertItemTemplate>
    Name:<br />
    <asp:TextBox ID="txtBox" runat="server" Text='<%# Bind("Author") %>' /><br />
    Text:<br />
    <asp:TextBox ID="txtText" runat="server" Text='<%# Bind("Text") %>'
        TextMode="MultiLine" /><br />
    <asp:Button runat="server" CommandName="Insert" Text="Post" /><br />
</InsertItemTemplate>     


 


Pay attetion at two things – data binding in the input controls and the CommandName attribute in the button. If you compile the website right now, you won’t see see the post form because you should define its position first, to do that add InsertItemPosition="FirstItem" to the ListView attributes, you can set it to LastItem however.

Now compile the project and try posting some comments. It’s working that is good.

DataPager

It’s time to add a pagination and see another new control in action. It is called DataPager. Add the following code to the LayoutTemlate of the ListView:

<asp:DataPager runat="server" PagedControlID="lvComments" PageSize="5">
    <Fields>
        <asp:NumericPagerField />
    </Fields>
</asp:DataPager> 

I suppose it’s pretty self-explanatory, PagedControlID defined the control we want to page, PageSize sets the number of entries per page. <asp:NumericPagerField /> says that we want to have the list of the page numbers. Compile it and try it in the browser.


I guess you noticed that it has an ugly postback in its URL. You can easily get rid of it by adding the QueryStringField attribute to the DataPager and of course by setting its value ;-).

<asp:DataPager runat="server" PagedControlID="lvComments" PageSize="5"
                    QueryStringField="page">

It looks much better now and you can send the link to the 10th page of your guestbook to a friend.

ASP.NET AJAX


At the final stage, let’s add some AJAX, so that the page doesn’t reload each time you post a comment. Visual Studio 2008 has a built-in ASP.NET AJAX library which is extremely easy in use.


Open Toolbox, expand AJAX Extensions and drop ScriptManager to the page. ScriptManager is a control that loads all the necessary JavaScript libraries needed for ASP.NET AJAX. If you forget to add ScriptManager, you’ll get an error.


So, we don’t want the whole page to be updated when posting a comment, we just want to update our ListView, so we are surrounding the ListView with UpdatePanel.

<asp:UpdatePanel runat="server">
    <ContentTemplate>
        <% List View code %>
    </ContentTemplate>
</asp:UpdatePanel>


Compile the website and post a comment, notice that the page doesn’t get reloaded this time.

Conclusion

There are a lot of cool features in ASP.NET that help you make your applications much faster than in ASP.NET 2.0. We have build a guestbook without writing a line of C# code. Of course this tutorial wasn't mean to cover all the features of ASP.NET 3.5, it doesn't cover the basics things, however you can find them on MSDN and on ww.asp.net.

Code

35NewFeatures.zip (5.80 kb)


Posted by Mike Borozdin on Sunday, June 22, 2008 6:48 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (6) | Post RSSRSS comment feed

Getting BlogEngine.NET To Work With The Local Time Zones

I noticed that the times of posts and comments were displayed in my local time zone. It must be very confusing for the users, especially if those times were the times of the comments they posted.


The first idea that came to my mind was just to use the GMT time zone. I set up the time zone offset in the blog settings, changed the templates, basically, I just put “GMT” after the time.


Anyway that still wasn’t good enough. I wanted the times of the posts and comments to be displayed in the local time zones of my readers.

Since it’s not possible to get the time zone offset of the user in ASP.NET without interacting with JavaScript, I decided to solve the problem in pure JavaScript. I just wrote a function that converted the string that represents the date and the time in GMT to the date and time of the local time zone of the user.

function ConvertToLocalDate(gmtDate)
{
    gmtDate = gmtDate.substr(gmtDate.indexOf(",", 0) + 1);
    
    var days = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
        "Saturday");
    var months = new Array("January", "February", "March", "April", "May", "June", "July", "August",
        "September", "November", "December");    
    
    var localDate = new Date();
    localDate.setTime(Date.parse(gmtDate) - localDate.getTimezoneOffset() * 60 * 1000);
    
    var sLocalDate = days[localDate.getDay()] + ", ";
    sLocalDate += months[localDate.getMonth()] + " ";
    sLocalDate += localDate.getDate() + ", ";
    sLocalDate += localDate.getFullYear() + " ";
    
    var hours = localDate.getHours();
    var amPm = "AM";
    if (hours >= 12)
    {
        amPm = "PM";
        if (hours >= 13)
        {
            hours -= 12;
        }
    }
    
    if (hours < 10)
    {
        hours = "0" + hours.toString();
    }
    
    var minutes = localDate.getMinutes();
    
    if (minutes < 10)
    {
        minutes = "0" + minutes.toString();
    }
    
    sLocalDate += hours + ":" + minutes + " " + amPm;
    
    return sLocalDate;
}


I placed this function in blog.js. Then I changed PostView.aspx and CommentView.aspx. I replaced:

<%=Post.DateCreated.ToLongDateString() + " " + Post.DateCreated.ToShortTimeString() %>

with

<script type="text/javascript">
    document.write(ConvertToLocalDate('<%=Post.DateCreated.ToLongDateString() + " " + Post.DateCreated.ToShortTimeString() %>'));
</script>

Posted by Mike Borozdin on Thursday, June 19, 2008 9:37 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (5) | Post RSSRSS comment feed

Syntax Highlighting In BlogEngine.NET

It is not obvious that BlogEngine.NET has a built-in syntax highlighting extension. I mean the current versions 1.3.1, I'm not sure about the old versions though. Anyway you can find it in the extensions settings, it is enabled by default.

So, if you need to paste a code snipped, just paste it in the text area and surround it with the [ code:<language>][/code ] tags

<language> may has one of the following values:

  • c#
  • vb
  • js
  • html
  • xml
  • tsql
  • msh (Windows PowerShell script language)

It can take some other parameters, like ln for toggling line numbers, however if you set this parameter your layout will get broken for some reasons.


Posted by Mike Borozdin on Wednesday, June 18, 2008 5:36 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Facebook Lose Millions

Of course, they don’t have the million losses; however they are missing millions of potential dollars and users.


You may have already heard about the Facebook clones. We have one in Russia, it’s called vkontakte.ru, there are more than 13 million registered users, while there are only about 80 thousand Russian users on Facebook.


Why? I mean why so many people in Russia use the clone instead of Facebook? Not only because the Facebook interface is English, but because it lacks Russian universities and schools, so it doesn’t fullfil its primary function – it doesn’t help people to find each other, it’s hard to find your classmates, it’s hard to find people you study in university with. I tried to add my university to the list, I wrote an e-mail, but for some reasons it wasn’t added.


I doubt if the Facebook management knows about a Russian social network with more than 13 million users, otherwise they would act, I think. I believe Facebook would have all the Russian universities and schools.


Russia isn’t the only country which has a huge Facebook clone; there are some German clones, Spanish, Chinese. What does it mean? It means that Facebook doesn’t suit the local needs. You can find the top 10 of the Facebook clones here.


I assume that is because Facebook was created for the internal use of the students of the single univestity, it started to support other universities and big organisations, now you can register even if you don't have a college or orgranisation e-mail, however I think that their policy hasn't changed. They are still operating on the US market mostly without taking the local markets into consideration, even though they translated their interfaces into several languages.


I may be wrong, Facebook may be planning to take the local markets by storm, I don’t know, I presume. But I think if Facebook were owned by a huge media company like Microsoft and Google, their policy would be much more aggressive and Facebook clones would be wiped out from the market.


Posted by Mike Borozdin on Monday, June 16, 2008 8:24 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

Difference Between Label.Text And TextBox.Text (WinForms) In Treating Line Breaks

I had a small project recently that outputted the results of some calculations to the label on the form, I replaced the label with a textbox and noticed that instead of the line breaks I had in the label I got a bunch of non-printed characters. I had the following code that worked fine for the label:

myLabel.Text += "\nNew Line";


However as I said it didn’t work properly for the textbox, however this one did work:

myTextBox.Text += "\r\nNew line";


This is good and it also works with the Label control, however you can do it better by using Environment.NewLine which represents the new line string on the current system:

myTextBox.Text += Environment.NewLine + "New line";


Tags: ,
Posted by Mike Borozdin on Saturday, June 14, 2008 7:59 PM GMT
Bookmark on MSDN   Add to Technorati Favorites  Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed