Wednesday, December 30, 2009

Eat, Dare or Dare Not

Recently watched a shocking movie about how industrialized food hurt people, animal and the environment. Great documentary, worth watching.

http://www.foodincmovie.com/about-the-film.php
http://www.foodincmovie.com/about-the-issues.php

Tuesday, December 29, 2009

C# Tutorial in the nutshell

The best online tutorial on C#, comprehensive and complete
http://www.csharp-station.com/Tutorial.aspx

Tmac: Say Bye to Rocket

自从姚明加盟火箭以来,和很多人一起加入了支持火箭的行列。但是一年年的失望而归,最终也就不怎么关注,随他去了。对于自己喜爱的球队,总是在那些失败的时刻哀其不幸,怒其不争。但是出于一点点同乡的私心,通常都是哀姚明之不幸,怒麦蒂之不争。毕竟,姚明一直是努力的,而天赋有限;麦蒂经常是偷懒的,但天赋顶尖。可惜向没法把科比的性格复制给麦蒂。

终于麦蒂要离开了。这次他似乎是争取了,但争取错了。雇主希望把每个手下的价值最大化,那他就能得到更多的剩余价值;雇员通常希望把自己的利益最大化。麦蒂想要拿到一份职业生涯最后的大合同,于是上赛季选择不告而别自动休战,以期在这个合同年爆发一下。可是彼时,正是火箭最需要领军人物带领他们冲击季后赛的成绩与票房的时刻。利益冲突之下,没有赢家。

中国人一直讲究集体的利益高于个人,美国人个人英雄主义更甚。不过在哪个国家,大家对信义的理解还是相同的。事到如今麦蒂得到的同情更少一些。因为火箭不是最先背信弃义的一方。于是,火箭虽然输,但输得有限。麦蒂要翻身,则难于上青天。

麦蒂的故事再次告诉我们,出来混迟早要还的。

Wednesday, December 23, 2009

Copenhagen fairytale

-- To explain the motivation behind the Copenhagen Summit.

Long long time ago, there was a big ship, on which there were 194 passengers. Unfortunately, no one was the ship captain although some always wanted to be. More unfortunately, the ship was leaking, therefore sinking slowly -- Well, if it was sinking quickly, even the most selfish or the most stupid person would take action. But most unfortunately, the ship was going down so slowly that some passengers chose to ignore that fact and started their bargain.

For some the passengers, for example a passenger called Maldives, it was a life-death issue because his cabinet was about to be taken by the sea. But a significant number of the passengers did not care. They were enjoying the sea view and growing their wealth as long as their cabinets were hardly affected. Among them, two major groups were formed. One group, headed by a passenger called America, owns almost all the luggage on the ship. Let's name them the rich. The other group, the brotherhood of the poor, were leaded by four big and strong guys -- China, India, Brazil, and Southafrica.

The first bargain took place in a cabinet called Japan. The theme was "How to slow down the ship-sinking process". In this bargain, everyone agrees that to prevent the ship from sinking we must throw away some of the luggage. And this was where the fighting began.

The poor pointed out that the rich had a lot to throw, "you have to throw another 40%".

The rich argues that what the poor owns were basically rubbish -- heavy and worthless; "you should throw all your belongings".

The poor replied, "That's OK if you compensate us for that". They asked the rich to contribute 0.5%-1% of their annual earnings, about $3,000 for compensation. What's more, they required the rich to teach the poor a few tips of getting richer.

The rich was angry on seeing such a request. "You must be daydreaming! We have already given you $100 a year. Don’t think of one more cent".

So that basically formed the arguments of the "Kyoto Protocol", which urges the rich to throw away their belongings. It targeted at America in particular, who owns 1/5 of the luggage. America was very unhappy about it, thus declined signing the paper. America came out and shouted, "It is true that I own 1/5 of the luggage, but they are as valuable as 1/4 of the all. Look at that China, she owns 1/5 of the luggage as well, but only values 3% of the total. Her luggage is also growing the fastest!"

China couldn't hide behind the crowd any more. She stood out and talked to her poor cousins, "Brothers and sisters, I have been and will continue fighting on behave of you to seek for more benefit. Don't be afraid of the rich. They will suffer more and lose more from the sinking. Let's unite and fight."

The brotherhood of the poor regained their high momentum. They accused the rich to have broken the ship since 200 years ago. "We've only gotten on the ship for a few days ago while you have sit on it for years. It is you who have worn out the ship. So it’s reasonable for you to spend more to fix it." They were delighted to come up with such a unbeatable argument.

The rich was not going to give in. "We had no idea that the ship would sink one day; and we have carried out repairs everyday. You are still caring about getting rich all the time. If not us, you wouldn't know how to repair it or even noticing it is sinking! You owes us great debt."

In order to end this everlasting, all sat down in the cabinet of Denmark. However, the hope worn out quickly since neither side would like to sacrafice their own wishes. The only outcome was so-called the "Copenhagen Consensus", in which it states "We discovered and admit that, the ship is leaking, and will sink."

So, the passengers were satisfied to see the consensus was reached, which reflected a great effort by all. And, the voyage carries on happily ever after.

Merry Christmas!

Tuesday, December 22, 2009

Workrave

"Workrave is a program that assists in the recovery and prevention of Repetitive Strain Injury (RSI). The program frequently alerts you to take micro-pauses, rest breaks and restricts you to your daily limit."

Excellent free occupational-health gadget, a must-install for office workers.

More detail @
http://www.workrave.org/welcome/

Software to be downloaded @
http://prdownloads.sourceforge.net/workrave/workrave-win32-1.9.1-installer.exe?download

Sunday, December 20, 2009

Copenhagen 2009

The Copenhagen summit was supposed to find out a way to clean up the mess on the earth. In the end, it created more mess, produced more carbon emission by this event.

To look at the bright side, fortunately now the general public know how to pronounce "Copenhagen" and know who shitty politics is.

Actually, I am more looking forward to the South Africa 2010.

Thursday, December 17, 2009

人物总结

冰清玉洁武藤兰,三贞九烈小泽圆。
不近女色陈冠希,天生丽质金喜善。
坚持原创郭小四,低调沉稳数韩寒。
清心寡欲小日本,万恶帝国美利坚。
与邻为善以色列,安宁祥和阿富汗。
国强民富看朝鲜,宇宙起源在南韩。
民主典范金正日,和平斗士本拉丹。
从不掉线天涯网,从不删贴管理员。
优秀记者冬日娜,尖嘴猴腮毕福剑。
只讲真话西西踢维,人民喉舌焦点访谈。

天籁之音曾轶可,大家闺秀李宇春。
守口如瓶宋祖德,字正腔圆周杰伦。
洁身自好赵忠祥,铁汉无泪冷朱军。
水准专业孙正平,从不口误韩乔生。
貌若天仙芙蓉姐,百毒不侵满文军。
诚信经营陈天桥,永不模仿马化腾。
重庆好人谢才萍,无家可归贾君鹏。
低速行车杭州市,交通顺畅北京城。
舍己为人范跑跑,眉清目秀冯小刚。
用色淡雅张艺谋,代言保真唐国强。
物美价廉奥菲斯,低调奢华阿迪王。
学识渊博余秋雨,淡泊名利查良镛。
勤俭持家章小蕙,从不炒作张纪中。
白面书生奥巴马,没有炸弹巴格达。
和风细雨马景涛,苗条骨感沈殿霞。
高大威猛属梅西,从不假摔是C罗。
料事如神贝球王,只争第一是国安。
足坛巨擘李大帝,世界强队国足男。
文明执法闵行区,国虎出没镇坪县。

干净公平全运会,春风拂面好 。
无毒无害三鹿奶,营养健康方便面。
强身健体俯卧撑,安全游戏躲猫猫。
爱管闲事酱油党,不明真相老百姓。
水深火热蛮夷众,欢欣鼓舞天朝民

Should I use a #temp table or a @table variable?

From:
http://databases.aspfaq.com/database/should-i-use-a-temp-table-or-a-table-variable.html

In a stored procedure, you often have a need for storing a set of data within the procedure, without necessarily needing that data to persist beyond the scope of the procedure. If you actually need a table structure, there are basically four ways you can "store" this data: local temporary tables (#table_name), global temporary tables (##table_name), permanent tables (table_name), and table variables (@table_name).

There is a partial list of questions and answers about table variables, including some differences between table variables and #temp tables, in KB #305977 - INF: Frequently Asked Questions - SQL Server 2000 - Table Variables.


Local Temporary Tables

CREATE TABLE #people
(
id INT,
name VARCHAR(32)
)

A temporary table is created and populated on disk, in the system database tempdb — with a session-specific identifier packed onto the name, to differentiate between similarly-named #temp tables created from other sessions. The data in this #temp table (in fact, the table itself) is visible only to the current scope (usually a stored procedure, or a set of nested stored procedures). The table gets cleared up automatically when the current procedure goes out of scope, but you should manually clean up the data when you're done with it:

DROP TABLE #people

This will be better on resources ("release early") than if you let the system clean up *after* the current session finishes the rest of its work and goes out of scope.

A common use of #temp tables is to summarize/compact/reorganize data coming from another stored procedure. So, take this example, which pares down the results of the system procedure sp_who2 into only the SPID, Status, and HostName of *active* processes that are *not* part of the regular operation of the system:

CREATE TABLE #sp_who3
(
SPID INT,
Status VARCHAR(32) NULL,
Login SYSNAME NULL,
HostName SYSNAME NULL,
BlkBy SYSNAME NULL,
DBName SYSNAME NULL,
Command VARCHAR(32) NULL,
CPUTime INT NULL,
DiskIO INT NULL,
LastBatch VARCHAR(14) NULL,
ProgramName VARCHAR(32) NULL,
SPID2 INT
)

INSERT #sp_who3 EXEC sp_who2 'active'

SELECT SPID, Status, HostName FROM #sp_who3
WHERE spid > 15

DROP TABLE #sp_who3

One of the main benefits of using a #temp table, as opposed to a permanent table, is the reduction in the amount of locking required (since the current user is the only user accessing the table), and also there is much less logging involved. (You could also increase this performance by placing tempdb on a separate drive... but that's another story.)

One minor problem with #temp tables is that, because of the session-specific identifier that is tacked onto the name, the name you give it is limited to 116 characters, including the # sign (while other table types are limited to 128). If you try, you will see this:

Server: Msg 193, Level 15, State 1, Line 1
The object or column name starting with '#' is too long. The maximum length is 116 characters.

Hopefully this won't be a limitation in your environment, because I can't imagine a table name that long being useful or manageable.

Another potential problem with #temp tables is that, if you enter a transaction and use a #temp table, and then cancel without ever issuing a ROLLBACK or COMMIT, you could be causing unnecessary locks in tempdb (for more information, see KB #159747).


Global Temporary Tables

CREATE TABLE ##people
(
id INT,
name VARCHAR(32)
)

Global temporary tables operate much like local temporary tables; they are created in tempdb and cause less locking and logging than permanent tables. However, they are visible to all sessions, until the creating session goes out of scope (and the global ##temp table is no longer being referenced by other sessions). If two different sessions try the above code, if the first is still active, the second will receive the following:

Server: Msg 2714, Level 16, State 6, Line 1
There is already an object named '##people' in the database.

I have yet to see a valid justification for the use of a global ##temp table. If the data needs to persist to multiple users, then it makes much more sense, at least to me, to use a permanent table. You can make a global ##temp table slightly more permanent by creating it in an autostart procedure, but I still fail to see how this is advantageous over a permanent table. With a permanent table, you can deny permissions; you cannot deny users from a global ##temp table.


Permanent Tables

CREATE TABLE people
(
id INT,
name VARCHAR(32)
)

A permanent table is created in the local database, however you can (unlike #temp tables) choose to create a table in another database, or even on another server, for which you have access. Like global ##temp tables, a permanent table will persist the session in which it is created, unless you also explicitly drop the table. (For contention and concurrency reasons, creating a "temporary" permanent table in this manner doesn't really make a lot of sense.) If you are planning to create a permanent table when the procedure runs, you should check to see if it exists, in order to avoid errors like the one mentioned above. For more information about checking for the existence of both local #temp tables and permanent tables, see Article #2458.

Like global ##temp tables, there seems to be little reason to use a permanent table unless the data is going to persist... and if that is the case, why not create the permanent table before the stored procedure is ever run, thereby eliminating all the CREATE / DROP logic?


Table Variables

DECLARE @people TABLE
(
id INT,
name VARCHAR(32)
)

A table variable is created in memory, and so performs slightly better than #temp tables (also because there is even less locking and logging in a table variable). A table variable might still perform I/O to tempdb (which is where the performance issues of #temp tables make themselves apparent), though the documentation is not very explicit about this.

Table variables are automatically cleared when the procedure or function goes out of scope, so you don't have to remember to drop or clear the data (which can be a good thing or a bad thing; remember "release early"?). The tempdb transaction log is less impacted than with #temp tables; table variable log activity is truncated immediately, while #temp table log activity persists until the log hits a checkpoint, is manually truncated, or when the server restarts.

Table variables are the only way you can use DML statements (INSERT, UPDATE, DELETE) on temporary data within a user-defined function. You can create a table variable within a UDF, and modify the data using one of the above statements. For example, you could do this:

CREATE FUNCTION dbo.example1
(
)
RETURNS INT
AS
BEGIN
DECLARE @t1 TABLE (i INT)
INSERT @t1 VALUES(1)
INSERT @t1 VALUES(2)
UPDATE @t1 SET i = i + 5
DELETE @t1 WHERE i < style="font-family: 'franklin gothic book',tahoma,verdana; font-size: 13px;">
DECLARE @max INT
SELECT @max = MAX(i) FROM @t1
RETURN @max
END
GO

However, try that with a #temp table:

CREATE FUNCTION dbo.example2
(
)
RETURNS INT
AS
BEGIN
CREATE TABLE #t1 (i INT)
INSERT #t1 VALUES(1)
INSERT #t1 VALUES(2)
UPDATE #t1 SET i = i + 5
DELETE #t1 WHERE i < style="font-family: 'franklin gothic book',tahoma,verdana; font-size: 13px;">
DECLARE @max INT
SELECT @max = MAX(i) FROM #t1
RETURN @max
END
GO

Results:

Server: Msg 2772, Level 16, State 1, Procedure example2, Line 7
Cannot access temporary tables from within a function.

Or try accessing a permanent table:

CREATE TABLE table1
(
id INT IDENTITY,
name VARCHAR(32)
)
GO

CREATE FUNCTION dbo.example3
(
)
RETURNS INT
AS
BEGIN
INSERT table1(name) VALUES('aaron')
RETURN SCOPE_IDENTITY()
END
GO

Results:

Server: Msg 443, Level 16, State 2, Procedure example3, Line 8
Invalid use of 'INSERT' within a function.

Table variables can lead to fewer stored procedure recompilations than temporary tables (see KB #243586 and KB #305977), and — since they cannot be rolled back — do not bother with the transaction log.

So, why not use table variables all the time? Well, when something sounds too good to be true, it probably is. Let's visit some of the limitations of table variables (part of this list was derived from KB #305977):
  • Table variables are only allowed in SQL Server 2000+, with compatibility level set to 80 or higher.

  • You cannot use a table variable in either of the following situations:

    INSERT @table EXEC sp_someProcedure

    SELECT * INTO @table FROM someTable

  • You cannot truncate a table variable.

  • Table variables cannot be altered after they have been declared.

  • You cannot explicitly add an index to a table variable, however you can create a system index through a PRIMARY KEY CONSTRAINT, and you can add as many indexes via UNIQUE CONSTRAINTs as you like. What the optimizer does with them is another story. One thing to note is that you cannot explicitly name your constraints, e.g.:

    DECLARE @myTable TABLE
    (
    CPK1 int,
    CPK2 int,
    CONSTRAINT myPK PRIMARY KEY (CPK1, CPK2)
    )

    -- yields:
    Server: Msg 156, Level 15, State 1, Line 6
    Incorrect syntax near the keyword 'CONSTRAINT'.

    -- yet the following works:
    DECLARE @myTable TABLE
    (
    CPK1 int,
    CPK2 int,
    PRIMARY KEY (CPK1, CPK2)
    )

  • You cannot use a user-defined function (UDF) in a CHECK CONSTRAINT, computed column, or DEFAULT CONSTRAINT.

  • You cannot use a user-defined type (UDT) in a column definition.

  • Unlike a #temp table, you cannot drop a table variable when it is no longer necessary—you just need to let it go out of scope.

  • You cannot generate a table variable's column list dynamically, e.g. you can't do this:

    SELECT * INTO @tableVariable

    -- yields:

    Server: Msg 170, Level 15, State 1, Line 1
    Line 1: Incorrect syntax near '@tableVariable'.

    You also can't build the table variable inside dynamic SQL, and expect to use it outside that scope, e.g.:

    DECLARE @colList VARCHAR(8000), @sql VARCHAR(8000)
    SET @colList = 'a INT,b INT,c INT'
    SET @sql = 'DECLARE @foo TABLE('+@colList+')'
    EXEC(@sql)
    INSERT @foo SELECT 1,2,3

    -- this last line fails:

    Server: Msg 137, Level 15, State 2, Line 5
    Must declare the variable '@foo'.

    This is because the rest of the script knows nothing about the temporary objects created within the dynamic SQL. Like other local variables, table variables declared inside of a dynamic SQL block (EXEC or sp_executeSQL) cannot be referenced from outside, and vice-versa. So you would have to write the whole set of statements to create and operate on the table variable, and perform it with a single call to EXEC or sp_executeSQL.

  • The system will not generate automatic statistics on table variables. Likewise, you cannot manually create statistics (statistics are used to help the optimizer pick the best possible query plan).

  • An INSERT into a table variable will not take advantage of parallelism.

  • A table variable will always have a cardinality of 1, because the table doesn't exist at compile time.

  • Table variables must be referenced by an alias, except in the FROM clause. Consider the following two scripts:

    CREATE TABLE #foo(id INT)
    DECLARE @foo TABLE(id INT)
    INSERT #foo VALUES(1)
    INSERT #foo VALUES(2)
    INSERT #foo VALUES(3)
    INSERT @foo SELECT * FROM #foo

    SELECT id
    FROM @foo
    INNER JOIN #foo
    ON @foo.id = #foo.id

    DROP TABLE #foo

    The above fails with the following error:

    Server: Msg 137, Level 15, State 2, Line 11
    Must declare the variable '@foo'.

    This query, on the other hand, works fine:

    SELECT id
    FROM @foo f
    INNER JOIN #foo
    ON f.id = #foo.id


  • Table variables are not visible to the calling procedure in the case of nested procs. The following is legal with #temp tables:

    CREATE PROCEDURE faq_outer
    AS
    BEGIN
    CREATE TABLE #outer
    (
    letter CHAR(1)
    )

    EXEC faq_inner

    SELECT letter FROM #outer

    DROP TABLE #outer
    END
    GO

    CREATE PROCEDURE faq_inner
    AS
    BEGIN
    INSERT #outer VALUES('a')
    END
    GO


    EXEC faq_outer

    Results:

    letter
    ------
    a

    (1 row(s) affected)

    However, you cannot do this with table variables. The parser will find the error before you can even create it:

    CREATE PROCEDURE faq_outer
    AS
    BEGIN
    DECLARE @outer TABLE
    (
    letter CHAR(1)
    )

    EXEC faq_inner

    SELECT letter FROM @outer
    END
    GO

    CREATE PROCEDURE faq_inner
    AS
    BEGIN
    INSERT @outer VALUES('a')
    END
    GO

    Results:

    Server: Msg 137, Level 15, State 2, Procedure faq_inner, Line 4
    Must declare the variable '@outer'.

    For more information about sharing data between stored procedures, please see this article by Erland Sommarskog.

Conclusion

Like many other areas of technology, there is no "right" answer here. For data that is not meant to persist beyond the scope of the procedure, you are typically choosing between #temp tables and table variables. Your ultimate decision should depend on performance and reasonable load testing. As your data size gets larger, and/or the repeated use of the temporary data increases, you will find that the use of #temp tables makes more sense. Depending on your environment, that threshold could be anywhere — however you will obviously need to use #temp tables if any of the above limitations represents a significant roadblock.

Monday, December 14, 2009

2009球界红人

2009年,在我比较熟悉的足球界,最红的当属Lionel Messi。拿了金球,风头无两。
在我很不熟悉的高尔夫球界,最红的当属Tiger Woods。一个老婆一个坑,马上就有18坑。

Tiger,即老虎。
Lionel,即狮子。
所以2009是属于大型哺乳猫科动物的。

特别提名,香港男足。完成了连中国男足都无法完成的任务:日前在东亚运男足决赛中,击败日本,取得冠军。中国男足上回取得国际赛事冠军是在……上世纪。

Sunday, December 13, 2009

中文名

中国人起名字很讲究,音形意要俱佳,还要看属相风水生辰八字,然后断个五行。遇到大家族有个族谱,名字中要配合辈分。有些字还要避尊者讳,不能用。所以起名,难。

今天想到了一个笑话。生第一个孩子,就叫天赐。第二个叫天佑。第三个叫天养。生到第四个,就叫添乱吧。

Friday, December 4, 2009

Switch Statement in C++ and C#

We all know that in C++, the following switch statement is not conventional, but perfectly fine.

char keystroke = getch();
switch( keystroke ) {
case 'a':
case 'b':
case 'c':
case 'd':
KeyABCDPressed();
break;
case 'e':
KeyEPressed();
break;
default:
UnknownKeyPressed();
break;
}


But in C#, this is not OK. "C# does not support an implicit fall through from one case label to another. The one exception is if a case statement has no code." Therefore, C# does not support implicit "goto" with "switch". But why?

Thursday, December 3, 2009

Excel & VBA Auto-formatting report

This is my first "developped-from-scratch" VBA script.

Sub FormatReport()

'Add total footer
Dim lastRow As Integer
Dim lastCol As Integer

lastRow = [A65536].End(xlUp).Row + 1
lastCol = [VV1].End(xlToLeft).Column

Range(Cells(lastRow, 1), Cells(lastRow, 1)).Value = "TOTAL"

Dim col As Integer
col = 2
Do Until col = lastCol
Range(Cells(lastRow, col), Cells(lastRow, col)).Select
R = ActiveCell.Row
C = ActiveCell.Column
If IsNumeric(Cells(2, C)) And Not IsEmpty(Cells(2, c)) Then
ActiveCell.Value = Application.sum(Range(Cells(2, C), Cells(R, C)))
End If
col = col + 1
Loop

'Format cells
col = 2
Do Until col = lastCol
'Range("B2", Cells(lastRow, lastCol)).Select
Range(Cells(2, col), Cells(lastRow, col)).Select
If IsNumeric(Cells(2, col)) Then
Selection.NumberFormat = "$#,##0"
End If
If IsDate(Cells(2, col)) Then
Selection.NumberFormat = "m/d/yyyy"
End If
Cells.EntireColumn.AutoFit
col = col + 1
Loop

'Format footer
Range(Cells(lastRow, 1), Cells(lastRow, lastCol)).Select
With Selection.Interior
.ColorIndex = 3
.Pattern = xlSolid
End With
Selection.Font.ColorIndex = 2
Selection.Font.Bold = True

'Format header
Range(Cells(1, 1), Cells(1, lastCol)).Select
Selection.Font.Bold = True
With Selection.Interior
.ColorIndex = 3
.Pattern = xlSolid
End With
Selection.Font.ColorIndex = 2
Range(Cells(1, 2), Cells(1, lastCol)).Select
With Selection
.HorizontalAlignment = xlRight
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With

'Insert new row
Rows("1:1").Select
Selection.Insert Shift:=xlDown
Range(Cells(1, 1), Cells(1, lastCol)).Select
With Selection.Interior
.ColorIndex = 3
.Pattern = xlSolid
End With
Selection.Font.ColorIndex = 2
Selection.Font.Bold = True
Range(Cells(1, 1), Cells(1, lastCol)).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Selection.Merge

'Add header to new row
Dim month As String
month = Application.InputBox("Enter Month and Year for the report header", "Enter Date", "January 2009")

Range(Cells(1, 1), Cells(1, lastCol)).Select
ActiveCell.FormulaR1C1 = "REPORT FOR " + month
Range(Cells(1, 1), Cells(1, lastCol)).Select
With Selection.Font
.Name = "Arial"
.Size = 14
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
End With

End Sub

Excel & VBa: find last row, column, cell in an Excel (work)sheet

Source:
http://www.ozgrid.com/VBA/ExcelRanges.htm

The following page contains some usefull (general) vba code that can be used to find the last row, columnand/or cell in an Excel (work)sheet.

Find the last used cell, before a blank in a Column:
Sub LastCellBeforeBlankInColumn()
Range("A1").End(xldown).Select
End Sub

Find the very last used cell in a Column:
Sub LastCellInColumn()
Range("A65536").End(xlup).Select
End Sub

Find the very last used cell in a Column:
Sub LastCellInColumn()
Range("A65536").End(xlup).Select
End Sub

Find the last cell, before a blank in a Row:
Sub LastCellBeforeBlankInRow()
Range("A1").End(xlToRight).Select
End Sub

Find the very last used cell in a Row:
Sub LastCellInRow()
Range("IV1").End(xlToLeft).Select
End Sub

Find the very last used cell on a Worksheet:
Sub Demo()
Cells.Find(What:="*", After:=[A1], SearchDirection:=xlPrevious).Select
End Sub

Find the last used Row on a Worksheet:
Sub FindLastRow()
Dim LastRow As Long

If WorksheetFunction.CountA(Cells) > 0 Then
'Search for any entry, by searching backwards by Rows.
LastRow = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
MsgBox LastRow
End If
End Sub

Find the last used Column on a Worksheet:
Sub FindLastColumn()
Dim LastColumn As Integer
If WorksheetFunction.CountA(Cells) > 0 Then
'Search for any entry, by searching backwards by Columns.
LastColumn = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
MsgBox LastColumn
End If
End Sub

==============================================

Wednesday, December 2, 2009

Cities for living

In Shanghai, I often asked myself, "Why I am here".
In HongKong, I often asked myself, "How long I will be here".
In some cities like Goteborg, I was told, "Welcome here".
In Sydney, I am here but people (e.g., DIAC) question "Why you are here".

Tuesday, December 1, 2009

25 Movie quotes

  "Stupid is as stupid does"
  famous quote by Michael Conner Humphreys (young Forrest) of Forrest Gump

  "Bond, James Bond"
  quote from numerous James Bond movies

  "Frankly my dear, I don't give a damn"
  quote from Clark Gable (Rhett Butler) in Gone with the Wind

  "What we have here is a failure to communicate"
  quote from Cool Hand Luke

  "You're gonna need a bigger boat"
  quote from Roy Schneider (Police Chief Martin Brody) in Jaws

  "Say hello to my Little Friend"
  quote by Al Pacino (Tony Montana) - Scarface

  "I feel the need - the need for speed"
  Quote from Tom Cruise (Maverick) in Top Gun

  "You know you drive almost slow enough to drive Miss Daisy"
  quote by Will Smith in Bad Boys

  "I'm the king of the world"
  quote by Leonardo DiCaprio (Jack Dawson) in Titanic

  "Ditto"
  quote from Patrick Swayze (Sam) in Ghost

  "You can't handle the truth"
  quote from Jack Nicholson (Colonel Jessup) in A Few Good Men

  "Show me the money"
  quote from Cuba Gooding Jr. (Ron Tidwell) in Jerry McGuire

  "Houston, we have a problem"
  quote from Tom Hanks (Jim Lowell) in Apollo 13

  "Here's looking at you kid"
  quote from Humphrey Bogart (Rick Blaine) in Casablanca

  "There's no crying in baseball"
  quote from Tom Hanks (Jimmy Dugan) in A League of Their Own

  "I'll Be Back"
  quote from Arnold Schwarzenegger from Terminator

  "I'll get you my pretty"
  quote from Wicked Witch of the West, Wizards of Oz

  "Go ahead make my day"
  quote by Clint Eastwood (Harry Callahan) in Sudden Impact

  "Well, nobody's perfect"
  quote from Joe E. Brown (Osgood Fielding III) in Some Like it Hot

  "Keep your friends close, but your enemies closer"
  quote from Al Pacino (Michael Corleone) in Godfather Part II

  "Snap out of it"
  quote from Cher (Loretta Castorini) in Moonstruck

  "You had me at hello"
  quote by Rene Zellweger (Dorothy Boyd) in Jerry McGuire

  "You talkin' to me?"
  famous quote by Robert De Niro (Travis Bickle) in Taxi Driver

  "After all, tomorrow is another day"
  quote from Vivien Leigh (Scarlett O'Hare) in Gone with the Wind

  "There's no place like home"
  quote from Judy Garland (Dorothy Gale) in Wizards of Oz