Showing posts with label Reporting. Show all posts
Showing posts with label Reporting. Show all posts

Thursday, January 8, 2009

SSRS Reports Rotate Text Or Split Alphabet Per Line

Few days ago my client requested a report, which required rotation of text and alphabet by 45 degree. Expected output was something Like this:





















Many of you may know that you can rotate a text in textbox by setting WritingMode to "tb-rl", which will rotate the text and it will look something like this:

















In order to rotate text at desired angle do following:
(1) create an image with desired text
(2) rotate that image
(3) import it to the image box in report

Add System.Drawing to the references by going to the Report Properties -> References.

for step1 use following function:
Function CreateImage(ByVal sImageText As String, ByVal FontType As String, ByVal FontSize As Integer) As System.Drawing.Bitmap
'Create an image from scratch
Dim bmpImage As New Drawing.Bitmap(1, 1)
Dim iWidth As Integer = 0
Dim iHeight As Integer = 0
'Create the Font object for the image text drawing.
Dim MyFont As New Drawing.Font(FontType, FontSize, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point)
'Create a graphics object to measure the text's width and height.
Dim MyGraphics As Drawing.Graphics = Drawing.Graphics.FromImage(bmpImage)
'This is where the bitmap size is determined.
iWidth = MyGraphics.MeasureString(sImageText, MyFont).Width
iHeight = MyGraphics.MeasureString(sImageText, MyFont).Height
'// Create the bmpImage again with the correct size for the text and font.
bmpImage = New Drawing.Bitmap(bmpImage, New Drawing.Size(iWidth, iHeight))
'// Add the colors to the new bitmap.
MyGraphics = Drawing.Graphics.FromImage(bmpImage)
MyGraphics.Clear(Drawing.Color.White)
MyGraphics.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
MyGraphics.DrawString(sImageText, MyFont, New Drawing.SolidBrush(Drawing.Color.Black), 0, 0)
MyGraphics.Flush()
Return bmpImage
End Function






for step2 use following function:



Function RotateImage(ByVal bm_in As System.Drawing.Bitmap, ByVal RotationAngle As Integer) As System.Drawing.Bitmap
Dim wid As Single = bm_in.Width
Dim hgt As Single = bm_in.Height
Dim corners As System.Drawing.Point() = { _
New System.Drawing.Point(0, 0), _
New System.Drawing.Point(wid, 0), _
New System.Drawing.Point(0, hgt), _
New System.Drawing.Point(wid, hgt)}
' Translate to center the bounding box at the origin.
Dim cx As Single = wid / 2
Dim cy As Single = hgt / 2
Dim i As Long
For i = 0 To 3
corners(i).X -= cx
corners(i).Y -= cy
Next i
' Rotate.
Dim theta As Single = Single.Parse(RotationAngle) * System.Math.PI _
/ 180.0
Dim sin_theta As Single = System.Math.Sin(theta)
Dim cos_theta As Single = System.Math.Cos(theta)
Dim X As Single
Dim Y As Single
For i = 0 To 3
X = corners(i).X
Y = corners(i).Y
corners(i).X = X * cos_theta + Y * sin_theta
corners(i).Y = -X * sin_theta + Y * cos_theta
Next i
' Translate so X >= 0 and Y >=0 for all corners.
Dim xmin As Single = corners(0).X
Dim ymin As Single = corners(0).Y
For i = 1 To 3
If xmin > corners(i).X Then xmin = corners(i).X
If ymin > corners(i).Y Then ymin = corners(i).Y
Next i
For i = 0 To 3
corners(i).X -= xmin
corners(i).Y -= ymin
Next i
' Create an output Bitmap and Graphics object.
Dim bm_out As New System.Drawing.Bitmap(CInt(-2 * xmin), CInt(-2 * _
ymin))
Dim gr_out As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bm_out)
' Drop the last corner lest we confuse DrawImage,
' which expects an array of three corners.
ReDim Preserve corners(2)
' Draw the result onto the output Bitmap.
gr_out.Clear(Drawing.Color.White)
gr_out.DrawImage(bm_in, corners)
gr_out.Flush()
' Display the result.
Return bm_out
End Function






for step3 use following function:



Function StreamImage(ByVal bmpImage As System.Drawing.Bitmap)
Dim stream As IO.MemoryStream = New IO.MemoryStream
Dim bitmapBytes As Byte()
'Create bitmap stream
bmpImage.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg)
bitmapBytes = stream.ToArray
stream.Close()
bmpImage.Dispose()
Return bitmapBytes
End Function
Finally execute all together:
Use following code:
Function Create_RotateAndStreamImage(ByVal sImageText As String, ByVal FontType As String, ByVal FontSize As Integer, ByVal RotationAngle As Integer)
'Create a blank image
Dim bmpImage As New Drawing.Bitmap(1, 1)
'Create an image from scratch
bmpImage = CreateImage(sImageText, FontType, FontSize)
'Rotate Image at desired Angle
bmpImage = RotateImage(bmpImage, RotationAngle)
Return StreamImage(bmpImage)
Return bmpImage
End Function
It gives desired results
buy using following expression:

= Code.Create_RotateAndStreamImage("TEJAS", "Microsoft Sans Serif", 14, 45)


Incase some of you may want to get following outcome:






So, now you have to rotate the alphabets, there isn't a builtin function available to rotate alphabets.
Anohter way is do not rotate text, just split word in to aphabet per line. You can use "& vbCrLf & " in between two alphabet to go to next line.


I used following vb code to do that:
Public Function Split(Word As String) As String
Dim TempWord As String
Dim SplitTemp As String
Split = ""
TempWord = Word
Do While Len(TempWord) > 0
SplitTemp = Left(TempWord, 1)
Split = Split & vbCrLf & SplitTemp
TempWord = Right(TempWord, Len(TempWord) - 1)
Loop
End Function

And use following expression:

=Code.Split("TEJAS")