2010年7月29日 星期四

Add Multithreading to Your VB.NET Applications

原出處

Working with Threads
VB.NET makes it easy to start working with threads. There are some subtleties that we will explore later, but let's jump in and create a simple form that spawns a new thread to run a background process. The first thing we will need to do is create the background task that will be run on the new thread. The following code executes a rather long running process—an infinite loop:

Private Sub BackgroundProcess()
Dim i As Integer = 1

Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Loop
End SubThis code loops infinitely and adds an item to a listbox on a form for each iteration. As a side note, if you are not familiar with VB.NET then you may have noticed a few other things in this code that you could not do in VB6:
Assign values to a variable when declaring the variable Dim i As Integer = 1
Use the += operator i += 1 Instead of i = i + 1
The Call keyword has been removed
Once we have a worker process, we need to assign this block of code to a new thread and start its execution. To do this we use the Thread object that is part of the System.Threading namespace in the .NET framework classes. When we instantiate a new Thread class we pass it a reference to the code block we want to execute in the constructor of the Thread class. The following code creates a new Thread object and passes it a reference to BackgroundProcess:
Dim t As Thread
t = New Thread(AddressOf Me.BackgroundProcess)
t.Start()
The AddressOf operator creates a delegate object to the BackgroundProcess method. A delegate within VB.NET is a type-safe, object-oriented function pointer. After the thread has been instantiated, you begin the execution of the code by calling the Start() method of the thread.





Keep It Under Control
After the thread is started, you have some control over the state of it by using methods of the Thread object. You can pause a thread's execution by calling the Thread.Sleep method. This method takes an integer value that determines how long the thread should sleep. If you wanted to slow down the addition of items to the listbox in the example above, place a call to the sleep method in this code:

Private Sub BackgroundProcess()
Dim i As Integer = 1

Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Thread.CurrentThread.Sleep(2000)
Loop
End SubCurrentThread is a public static property that allows you to retrieve a reference to the currently running thread.
You can also place a thread into the sleep state for an indeterminate amount of time by calling Thread.Sleep (System.Threading.Timeout.Infinite). To interrupt this sleep you can call the Thread.Interrupt method.

Similar to Sleep and Interrupt are Suspend and Resume. Suspend allows you to block a thread until another thread calls Thread.Resume. The difference between Sleep and Suspend is that the latter does not immediately place a thread in the wait state. The thread does not suspend until the .NET runtime determines that it is in a safe place to suspend it. Sleep will immediately place a thread in a wait state.

Lastly, Thread.Abort stops a thread from executing. In our simple example, we would want to add another button on the form that allows us to stop the process. To do this all we would have to do is call the Thread.Abort method as follows:

Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
t.Abort()
End SubThis is where the power of multithreading can be seen. The UI seems responsive to the user because it is running in one thread and the background process is running in another thread. The cancel button immediately responds to the user's click event and processing stops.







Passing Data Through Multithreaded Procedures
The last example shows a rather simple situation. Multithreading has many complications that you have to work out when you program. One issue that you will run into is passing data to and from the procedure passed to the constructor of the Thread class. That is to say, the procedure you want to kick off on another thread cannot be passed any parameters and you cannot return data from that procedure. This is because the procedure you pass to the thread constructor cannot have any parameters or return value. To get around this, wrap your procedure in a class where the parameters to the method are written as fields of the class.

A simple example of this would be if we had a procedure that calculated the square of a number:

Function Square(ByVal Value As Double) As Double
Return Value * Value
End FunctionTo make this procedure available to be used in a new thread we would wrap it in a class:
Public Class SquareClass
Public Value As Double
Public Square As Double

Public Sub CalcSquare()
Square = Value * Value
End Sub
End ClassUse this code to start the CalcSquare procedure on a new thread. following code:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

Dim oSquare As New SquareClass()

t = New Thread(AddressOf oSquare.CalcSquare)

oSquare.Value = 30

t.Start()
End SubNotice that after the thread is started, we do not inspect the square value of the class, because it is not guaranteed to have executed once you call the start method of the thread. There are a few ways to retrieve values back from another thread. The easiest way is to raise an event when the thread is complete. We will examine another method in the next section on thread synchronization. The following code adds the event declarations to the SquareClass.
Public Class SquareClass
Public Value As Double
Public Square As Double

Public Event ThreadComplete(ByVal Square As Double)

Public Sub CalcSquare()
Square = Value * Value
RaiseEvent ThreadComplete(Square)
End Sub
End ClassCatching the events in the calling code has not changed much from VB6, you still declare the variables WithEvents and handle the event in a procedure. The part that has changed is that you declare that a procedure handles the event using the Handles keyword and not through the naming convention of Object_Event as in VB6.
Dim WithEvents oSquare As SquareClass

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

oSquare = New SquareClass()

t = New Thread(AddressOf oSquare.CalcSquare)

oSquare.Value = 30
t.Start()
End Sub

Sub SquareEventHandler(ByVal Square As Double) _
Handles oSquare.ThreadComplete

MsgBox("The square is " & Square)

End SubThe one thing to note with this method is that the procedure handling the event, in this case SquareEventHandler, will run within the thread that raised the event. It does not run within the thread from which the form is executing.







Synchronizing the Threads
VB.NET contains a few statements to provide synchronization of threads. In the Square example, you would want to synchronize the thread performing the calculation in order to wait for the calculation to complete so you can retrieve the result. Another example would be if you sort an array on a different thread and you would wait for that process to complete before using the array. To perform these synchronizations, VB.NET provides the SyncLockEnd SyncLock statement and the Thread.Join method.

SyncLock gains an exclusive lock to an object reference that is passed to it. By gaining this exclusive lock you can ensure that multiple threads are not accessing shared data or that the code is executing on multiple threads. A convenient object to use in order to gain a lock is the System.Type object associated with each class. The System.Type object can be retrieved using the GetType method:

Public Sub CalcSquare()
SyncLock GetType(SquareClass)
Square = Value * Value
End SyncLock
End SubLastly, the Thread.Join method allows you to wait for a specific amount of time until a thread has completed. If the thread completes before the timeout that you specify, Thread.Join returns True, otherwise it returns False. In the square sample, if we did not want to raise events, we could call the Thread.Join method to determine if the calculation has finished. The code would look like the following:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

Dim oSquare As New SquareClass()

t = New Thread(AddressOf oSquare.CalcSquare)

oSquare.Value = 30
t.Start()

If t.Join(500) Then
MsgBox(oSquare.Square)
End If
End SubThe one thing to note with this method is that the procedure handling the event, in this case SquareEventHandler, will run within the thread that raised the event. It does not run within the thread from which the form is executing.

VB.Net 效能監視器運用

原出處
***詳細還請至原作者那兒***
-------
' 匯入名稱空間
Imports System.Diagnostics
Imports System.Management

Public Class Form1

' Processor
Private Shared CPU_Core1 As PerformanceCounter = Nothing
Private Shared CPU_Core2 As PerformanceCounter = Nothing

' Page File
Private Shared PageFile_Usage As PerformanceCounter = Nothing
Private Shared PageFile_UsagePeak As PerformanceCounter = Nothing

' My.Computer.Info
Private Shared cptInfo As Devices.ComputerInfo = Nothing
' 查詢擷取管理物件
Private Shared Searcher As ManagementObjectSearcher = Nothing

Private Shared TotPhyMem As UInt64 = 0 ' Total Physical Memory
Private WithEvents tmr As New Timer ' Timer

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

' 宣告並建立 "效能計數器元件" 類別
' New PerformanceCounter(CategoryName,CounterName,InstanceName)
' CategoryName : 取得或設定這個效能計數器的效能計數器分類的名稱。
' CounterName : 取得或設定與這個 PerformanceCounter 執行個體相關的效能計數器的名稱。
' InstanceName : 取得或設定這個效能計數器的執行個體名稱。

' 可用 Environment.ProcessorCount 取得 CPU Core 核心數量
' Processor Core#0 核心1
CPU_Core1 = New PerformanceCounter("Processor", "% Processor Time", "0")
' Processor Core#1 核心2
CPU_Core2 = New PerformanceCounter("Processor", "% Processor Time", "1")

' 分頁檔
PageFile_Usage = New PerformanceCounter("Paging File", "% Usage", "_Total")
' 尖峰分頁檔
PageFile_UsagePeak = New PerformanceCounter("Paging File", "% Usage Peak", "_Total")

cptInfo = New Devices.ComputerInfo() ' 取電腦資訊

tmr.Interval = 999 ' Timer.Interval 屬性 : 取得或設定引發 Elapsed 事件的間隔。
tmr.Start() ' 啟動 Timer

' 取得 CPU 名稱 (WMI)
For Each MngObj As ManagementObject In New ManagementObjectSearcher(New SelectQuery("Win32_Processor")).Get()
' Get Processor Name
imgLstBoxCPU.Items.Add(String.Format(" CPU : {0}", MngObj.GetPropertyValue("Name")), 1)
Next

GetProcessorInfo() ' 取得 CPU 資訊 (WMI)

' My.Computer.Info.TotalPhysicalMemory
TotPhyMem = cptInfo.TotalPhysicalMemory ' 取得全部實體記憶體

lbl實體記憶體.Text = KB2MB(TotPhyMem) ' 顯示到 Label

End Sub

Private Sub GetProcessorInfo() ' 取得 CPU 資訊 (WMI)

'使用 SelectQuery 物件可下 SELECT 陳述式查詢
'Select * From Win32_Processor 語法可省略 , 直接寫 WMI 類別名稱即可
Dim SelQry As New SelectQuery("Win32_Processor")

'使用 ManagementObjectSearcher 物件取回一個 WMI 物件基底之查詢的 集合物件(Collection)
Using MngObjSch As New ManagementObjectSearcher(SelQry)
' 使用 ManagementObjectSearcher.Get 方法, 叫用指定的 WMI 查詢,並傳回產生的集合。
' 列舉出 Win32_Processor WMI 類別中每一個處理器 (成員)
For Each MngObj As ManagementObject In MngObjSch.Get()
' 顯示 CPU 資訊
lstBox.Items.Add(String.Format("Caption : {0}", MngObj!Caption))
lstBox.Items.Add(String.Format("Manufacturer : {0}", MngObj!Manufacturer))
lstBox.Items.Add(String.Format("Number Of Logical Processors : {0}", MngObj!NumberOfLogicalProcessors))
lstBox.Items.Add(String.Format("L2 Cache Size : {0} KB", MngObj!L2CacheSize))
lstBox.Items.Add(String.Format("Current Clock Speed : {0} MHz", MngObj!CurrentClockSpeed))
lstBox.Items.Add(String.Format("Clock frequency : {0} MHz", MngObj!MaxClockSpeed))
lstBox.Items.Add(String.Format("CurrentVoltage : {0} V", MngObj!CurrentVoltage))
lstBox.Items.Add(String.Format("Number Of Cores : {0}", MngObj!NumberOfCores))
lstBox.Items.Add(String.Format("Address Width : {0}", MngObj!AddressWidth))
lstBox.Items.Add(String.Format("External Clock : {0} MHz", MngObj!ExtClock))
lstBox.Items.Add(String.Format("Data Width : {0}", MngObj!DataWidth))
lstBox.Items.Add(String.Format("Socket Designation : {0}", MngObj!SocketDesignation))
Next
End Using

End Sub

' Timer Tick 事件
Private Sub tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmr.Tick

Dim Core1 As Int32 = dgt2(CPU_Core1.NextValue) ' 取得 CPU 核心1 使用率
Dim Core2 As Int32 = dgt2(CPU_Core2.NextValue) ' 取得 CPU 核心2 使用率

lblCore1Usage.Text = String.Format("Core #0 {0} % ", Core1) ' 取得 CPU 核心1 使用率
lblCore2Usage.Text = String.Format("Core #1 {0} % ", Core2) ' 取得 CPU 核心2 使用率

Dim AvPhyMem As UInt64 = cptInfo.AvailablePhysicalMemory ' 取得可用實體記憶體
Dim TotVtMem As UInt64 = cptInfo.TotalVirtualMemory ' 取得全部虛擬記憶體
Dim AvVtNen As UInt64 = cptInfo.AvailableVirtualMemory ' 取得可用虛擬記憶體

lblAvPhyMem.Text = KB2MB(AvPhyMem) ' 顯示可用實體記憶體
lblTotVtMem.Text = KB2MB(TotVtMem) ' 顯示全部虛擬記憶體
lblAvVtNen.Text = KB2MB(AvVtNen) ' 顯示可用虛擬記憶體
lblRAMusage.Text = KB2MB(TotPhyMem - AvPhyMem) ' 顯示 RAM 已用

' 顯示分頁檔使用
lblPageFileUsage.Text = String.Format(" Page File {0:##0.00} %", PageFile_Usage.NextValue)
' 顯示分頁檔尖峰使用
lblPageFileUsagePeak.Text = String.Format(" Page File Peak {0:##0.00} %", PageFile_UsagePeak.NextValue)

' 顯示本程式使用記憶體
' Process.GetCurrentProcess.WorkingSet
' Process.GetCurrentProcess.WorkingSet64
bsi.Caption = String.Format("本程式記憶體 : {0} MB", KB2MB(Environment.WorkingSet))

End Sub

Private Shared Function KB2MB(ByVal kb As Long) As String
' 講 KB 轉 MB ( / 1024 / 1024 ) 並指定格式
' 四捨五入將值捨入至指定的小數點兩位。
Return Math.Round(kb / 2 ^ 20, 2).ToString("#,##0.00")
End Function

Private Shared Function dgt2(ByVal value As Single) As String
' 四捨五入將值捨入至指定的小數點兩位。
Return Math.Round(value, 2).ToString()
End Function

End Class

Activate a Running Application by process ID

原出處
---
Dim processID As Integer
processID = Shell("NOTEPAD.EXE", AppWinStyle.NormalFocus)
AppActivate(processID)
---
好用呀

Process class has properties for MainWindowTitle, Id, and ProcessName

Public Class Form1

Private WithEvents processView As New ListView() With {.Dock = DockStyle.Fill, .View = View.Details}
Private Const SW_RESTORE As Integer = 9
Public Declare Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean

Sub New()
InitializeComponent()
processView.Columns.Add("Process name")
processView.Columns.Add("Process id")
processView.Columns.Add("Main window title")
Me.Controls.Add(processView)
RefreshProcessView()
End Sub

Private Sub RefreshProcessView()
For Each lvi As ListViewItem In processView.Items
DirectCast(lvi, ProcessListViewItem).Dispose()
Next
For Each p As Process In Process.GetProcesses
processView.Items.Add(New ProcessListViewItem(p))
Next
' resize all columns so that all titles and contents can be seen.
For i As Integer = 0 To processView.Columns.Count - 1
processView.Columns(i).AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent)
Dim width As Integer = processView.Columns(i).Width
processView.Columns(i).AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
If width > processView.Columns(i).Width Then processView.Columns(i).Width = width
Next
End Sub

' Clear up the processes.
Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
For Each lvi As ListViewItem In processView.Items
DirectCast(lvi, ProcessListViewItem).Dispose()
Next
End Sub

Private Sub processView_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles processView.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim item As ProcessListViewItem = DirectCast(processView.GetItemAt(e.X, e.Y), ProcessListViewItem)
ShowWindow(item.Process.MainWindowHandle, SW_RESTORE)
End If
End Sub
End Class

Public Class ProcessListViewItem
Inherits ListViewItem
Implements IDisposable

Private disposedValue As Boolean = False ' To detect redundant calls
Private m_process As Process
Public ReadOnly Property Process() As Process
Get
Return m_process
End Get
End Property

Sub New(ByVal p As Process)
MyBase.New(p.ProcessName)
Me.SubItems.Add(p.Id.ToString)
Me.SubItems.Add(p.MainWindowTitle)
m_process = p
End Sub

' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
If process IsNot Nothing Then process.Dispose()
End If
End If
Me.disposedValue = True
End Sub

#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region

End Class

get active window processID

Declare Function GetForegroundWindow Lib "user32.dll" () As Int32

Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
ByVal hwnd As Int32, _
ByRef lpdwProcessId As Int32) As Int32

Public Function RetCurTitle() As String
Dim processID As Int32
GetWindowThreadProcessId(GetForegroundWindow(), processID)
Return Process.GetProcessById(processID).MainWindowTitle
End Function

2010年7月28日 星期三

VB.NET Sample code

Blog
http://vbnetsample.blogspot.com/

Start And Kill process

Process Class


Provides access to local and remote processes and enables you to start and stop local system processes.

Sample Code

1. Start notepad
System.Diagnostics.Process.Start("notepad")

2. Start winword
System.Diagnostics.Process.Start("WINWORD")

3. Start excel
System.Diagnostics.Process.Start("Excel")

4. Start ie and parameter
System.Diagnostics.Process.Start("IExplore.exe", "http://vbnetsample.blogspot.com/")

5. Kill It!!
' Kill all notepad process
Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("notepad")

For Each p As Process In pProcess
p.Kill()
Next

FindWindowEx Function

參考1
參考2
----------
_
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function

-(1)-
Dim tmpWnd&
tmpWnd = FindWindow("Shell_TrayWnd", "") 'Task bar
tmpWnd = FindWindowEx(tmpWnd, 0&, "TrayNotifyWnd", "") 'System tray
trayClock = FindWindowEx(tmpWnd, 0&, "TrayClockWClass", "") 'System tray clock

-(2)-
Dim tmpWnd&, clsName As String * 100, clsLen&
tmpWnd = FindWindow("Shell_TrayWnd", "") 'Task bar
tmpWnd = FindWindowEx(tmpWnd, 0&, "TrayNotifyWnd", "") 'System tray
trayClock = FindWindowEx(tmpWnd, 0&, "TrayClockWClass", "") 'System tray clock
If trayClock = 0 Then
tmpWnd = GetWindow(tmpWnd, GW_CHILD)
Do While tmpWnd <> 0
clsLen = GetClassName(tmpWnd, clsName, 100)
If Left(clsName, clsLen) = "TrayClockWClass" Then
trayClock = tmpWnd
Exit Do
End If
tmpWnd = GetWindow(tmpWnd, GW_HWNDNEXT)
Loop
End If

-(3)-
ShellTrayWnd& = FindWindow("Shell_TrayWnd", vbNullString)
TrayNotifyWnd& = FindWindowEx(ShellTrayWnd&, 0&, "TrayNotifyWnd", vbNullString)
TrayClockWClass& = FindWindowEx(TrayNotifyWnd&, 0&, "TrayClockWClass", vbNullString)

折扣,折讓 轉換計算

折扣:
50 折數:80 --->50*(80/100)=40

折讓:
50 折讓:10 --->(40/50)*100=80

ActiveReports

官網

又是新的一款報表,支援NET;可參考看看
----------------
ActiveReports為全世界的.NET開發者開創性地引入多種技術,包括:第一個Visual Basic報表生成器;第一個Visual Studio報表設計器;第一個代碼隱藏報表模型;第一個終端用戶報表設計器和第一個免發佈版稅的報表工具。

控件質量經過成千上萬用戶的測試

十幾年前,ActiveReports就成為第一個在Visual Basic集成開發環境(IDE)中使用的報表工具。那時起,COM版和現在的.NET版不僅僅被成千上萬的軟件開發者使用,而且也是眾多國際報表工具中唯一在日本和歐洲成功本土化,銷售和獲得支持的報表工具。總之,ActiveReports是久經考驗的報表技術,表現穩健(甚至我們的一些競爭對手認為我們的那些功能過於超前)。

豐富的報表工具集

ActiveReports在十年的顧客反饋和世界上超過50000軟件開發者的報表經歷基礎上提煉而成。購買了ActiveReports就相當於購買了一套完整的.NET報表工具。包括:升級工具;MS Access和其他報表轉換器;Visual Studio報表設計;終端用戶報表設計;圖表工具;條形碼;輸出插件及.NET報表軟件開發工具包(SDK)。

幾乎限制的自定義報表

ActiveReports幾乎是最靈活的報表工具。它提供擴展的隱藏代碼,針對報表創建的基於事件的API,運行時可跟蹤任何報表行為。使用ActiveReports的軟件開發者可以將高級的報表功能嵌入其應用程序中(甚至是一些看起來不現實的功能)。通過閱讀我們的案例瞭解 ActiveReports是如何為客戶將報表轉變為有競爭力的優勢。

直觀的Visual Studio報表設計

ActiveReports繼十年前與Visual Basic整合後,2008年又與Visual Studio結合,成為世界上第一款與Visual Studio相結合的、易用報表設計的報表工具。其報表設計也支持C#和第三方托管控制,並且在運行時,還為創建和自定義報表提供擴展的程序模型。

支持多種數據綁定

ActiveReports可將報表與多種數據源綁定,包括運行時未綁定的數據。也可改變源數據的性質,來提供特設(ad-hoc)的報表。ActiveReports支持OLEDB; XML;;.NET SQL 用戶; .NET集(如數據設置,數據視圖和數據表);任何支持iList接口的實體。

多種輸出格式

ActiveReports支持多種格式的報表輸出,包括:PDF,HTML,MHT,RTF,Excel (.XLS),純文本格式(.TXT),逗號分割文件格式(CSV),和TIFF格式。

易用的終端用戶報表工具

ActiveReports允許您在您的應用程序中托管報表設計器,並免費分發。終端用戶可編輯報表並下載保存報表佈局。另外,ActiveReports允許您監視並控制報表設計環境,自定義報表的外觀以滿足您終端用戶的要求。

世界級的報表性能和質量

如果您和超過50000的使用者一樣,敬佩ActiveReports世界級的質量和速度,你一定會更喜歡版本6。新版本有很多改進,以保證報表引擎的性能和質量。使其比以前更好,更快,更靈活。

豐富的控件和公共知識庫

一旦購買了ActiveReports和其他相關控件,您就走在了市場的尖端。您要相信,在最近十年,超過50,000的軟件開發者選擇了ActiveReports,並將他們的經驗和技巧都融入控件中,而且他們的經驗和技巧都已通過論壇、文章、博客和電郵形式發佈在網上。

無限制分發

ActiveReports .NET報表工具有靈活的免版稅的分發功能。您既可以通過.NET文件副本技術發佈也可以將其編譯進您的應用程序中。您可以忘記分發用戶的費用或像其他報表工具那樣出現無數的計費項目。

外部程序如何嵌套到窗体上

原出處

' API声明
Private Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer


' 调用
Dim ptrHandle As IntPtr ' 外部程序的句柄
Dim intLeft As Integer, intTop As Integer ' 外部程序在窗体内的位置
Dim intWidth As Integer, intHeight As Integer ' 外部程序在窗体内的大小

' 获取外部程序的句柄
ptrHandle = FindWindow(vbNullString, "Adobe photoshop") ' 引号中是外部程序的标题名
' 嵌入当前窗体
SetParent(ptrHandle, Me.Handle)
' 设置外部程序在窗体内的位置和大小(省略)

' 移动到指定的位置
MoveWindow(ptrHandle.ToInt32, intLeft, intTop, intWidth, intHeight, 1)

Application.Run 方法 (Form)

這code 待研究,因我未用過;記錄起來
-----------------------
.NET Framework 类库
Application.Run 方法 (Form)

在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。

命名空间:System.Windows.Forms
程序集:System.Windows.Forms(在 system.windows.forms.dll 中)


VB.NET code

'---------------------------------
Sub Main()
AddHandler g_ManageCmd.MsgRecv, AddressOf frmMain.lvwMsgManager_UpdateInvoke


'在当前线程上开始运行标准应用程序消息循环()
'Application.Run(New frmMain)
Application.Run(frmMain)

End Sub

'-------------------------------------------------------
'专门处理来自客户端消息的类,由sokcet.DataArrial()事件触发
'来自客户端的消息处理
Public Sub InfoFromClientHandler(ByVal ID As Integer, ByVal cmd As strtManageCommand)
'需要弹出提示窗口,具体的内容从缓冲区中获取,弹出窗口不能影响其他程序的执行,不能
'在当前线程上启动
RaiseEvent MsgRecv()

End Sub

'--------------------------------------------------------
'主窗体中,定义处理界面的委托和处理具体事件客户端信息来临时的事件MsgRecv
'委托
Public Delegate Sub lvwMsgManager_Invoke()

'更新
Public Sub lvwMsgManager_UpdateInvoke()
If Me.InvokeRequired Then
Me.Invoke(New lvwMsgManager_Invoke(AddressOf Me.lvwMsgManager_UpdateInvoke))
Else

Try
lvwMsgManager_Update()
Catch ex As Exception
ErrorHandler(ex.ToString)
End Try
End If
End Sub

ThreadPool 多執行緒

看到這個code不錯,記錄下來;待有空再來研究細節,此code 尚有問題..太多thread,會出問題
-----------
ReDim Class_relogin(ListView1.Items.Count - 1)
ReDim TPool(ListView1.Items.Count - 1)
Dim index As Integer
For i As Integer = 0 To ListView1.SelectedItems.Count - 1
index = Val(ListView1.SelectedItems.Item(i).SubItems(6).Text)
Class_relogin(index) = New Login()
ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf Class_relogin(index).ReLogin), index)

Next

2010年7月25日 星期日

Creating Sub-Reports Using Crystal Reports

Creating Sub-Reports Using Crystal Reports

java2s

Programming tutorials and source code examples
---------------------------------------------
Java
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
SCJP

C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source

VB.Net
VB.Net Tutorial
VB.Net by API

C / ANSI-C
C Tutorial
C++
C++ Tutorial
Visual C++ .NET

Oracle PL / SQL
Oracle PL/SQL Tutorial

SQL Server / T-SQL
SQL Server / T-SQL Tutorial
---------------------------------------------

2010年7月23日 星期五

CDO SSL sendmail

原出處
參考網址

Friday, July 2, 2010Send mail from your gmail account using VB6 CDO throught SMTP
The following is the function to send email from vb6 application using CDO object.


Public Function SendMail(toMail As String, subject As String, msgBody As String)
Dim lobj_cdomsg As CDO.Message
Set lobj_cdomsg = New CDO.Message
lobj_cdomsg.Configuration.Fields(cdoSMTPServer) = "smtp.gmail.com"
lobj_cdomsg.Configuration.Fields(cdoSMTPServerPort) = 465
lobj_cdomsg.Configuration.Fields(cdoSMTPUseSSL) = True
lobj_cdomsg.Configuration.Fields(cdoSMTPAuthenticate) = 1
lobj_cdomsg.Configuration.Fields(cdoSendUsername) = "username@gmail.com"
lobj_cdomsg.Configuration.Fields(cdoSendPassword) = "password"
lobj_cdomsg.Configuration.Fields(cdoSMTPConnectionTimeout) = 30
lobj_cdomsg.Configuration.Fields(cdoSendUsingMethod) = 2
lobj_cdomsg.Configuration.Fields.Update
lobj_cdomsg.To = toMail
lobj_cdomsg.From = "username@gmail.com"
lobj_cdomsg.subject = subject
lobj_cdomsg.HTMLBody = msgBody
lobj_cdomsg.Send
Set lobj_cdomsg = Nothing
End Function

2010年7月22日 星期四

控制金額小數點



程式內運用string.format(也可運用math.round) 來處理控制計算後的小數點
若在sql就只剩下round了
本例採用string.format

code
--------------------
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As Decimal = TextBox2.Text
Dim b As Decimal = TextBox3.Text
Dim d As Integer = TextBox4.Text
Dim c As Decimal = String.Format("{0:N" & d & "}", a * b)
TextBox1.Text = c
End Sub
End Class

資料作運算候如何把小數點第3位以下刪除

ToString("0.00")
或者
substring(0,AAA.IndexOf(".")+2) AAA就是數字變數

四捨五入

Math.Round (Decimal) 將十進位的值捨入至最近的整數。
受 .NET Compact Framework 支援。

Math.Round (Double) 將雙精度浮點數捨入至最接近的整數。
受 .NET Compact Framework 支援。

Math.Round (Decimal, Int32) 將十進位的值捨入至指定的精確度。
受 .NET Compact Framework 支援。

Math.Round (Decimal, MidpointRounding) 將十進位的值捨入至最近的整數。如果值介於兩個其他數字之間,參數會指定如何捨入該值。
Math.Round (Double, Int32) 將雙精度浮點數捨入至指定的精確度。
受 .NET Compact Framework 支援。

Math.Round (Double, MidpointRounding) 將雙精度浮點數捨入至最接近的整數。如果值介於兩個其他數字之間,參數會指定如何捨入該值。
Math.Round (Decimal, Int32, MidpointRounding) 將十進位的值捨入至指定的精確度。如果值介於兩個其他數字之間,參數會指定如何捨入該值。
Math.Round (Double, Int32, MidpointRounding) 將雙精度浮點數捨入至指定的精確度。如果值介於兩個其他數字之間,參數會指定如何捨入該值

String Function

Asc(String) => 傳回String第一個字元之ASCII Code.

Chr(ASCII) => 傳回ASCII對應之字元.

Cstr(數值參數) => 將數值參數轉換為字串.

Str(數值參數) =>將數值參數轉換為字串.

Val(文數字參數) => String轉為數字.

Cbool(運算式) => 傳回true or false.

Len(String) => 傳回String 之長度.

Left(String,取出之字元數) => substring from head.

Right(String, number) => substring from right.

Mid(String, no1, no2) => substring from #1 and total #2個字元.

Choose(#, str1, str2, str3) => 取出第#個字串.

Replace(String, String to be replaced, String to replace, 起始位置,取代次數,比較方法)

i. 比較方法CompareMethod.Binary: 大小寫不同

ii. 比較方法CompareMethod.text: 大小寫相同.

Lcase(String) => switch to Lower case.

Ucase(String) => switch to Upper case.

Ltrim(String) => trim() left side.

Rtrim(String) => trim() right side.

Trim(String) => trim() double side.

Instr(第n個字元,字串,指定搜尋的字串,比較方式) => 從第n個字元開始搜尋字串,找出指定的字串第一次出現的位置.

Space(n個空白字元) => generate n 個space.

Strcomp(String1, String2, 比較方式)

i. 1, String1 > String2

ii. 0, String1 = String2

iii. –1, String1 < String2

Strconv(String, 編寫樣式)

i. 編寫樣式VbStrConv.LowerCase: Upper to Lower

ii. 編寫樣式VbStrConv.UpperCase: Lower to Upper.

iii. 編寫樣式ProperCase: first letter à Upper; others à Lower.

iv. 編寫樣式VbStrConv.Wide: 半形 à 全形

v. 編寫樣式VbStrConv.Narrow: 全形 à 半形
StrReverse(String) => Reverse the String.

IsNumberic(運算式) => To see if 運算式 is number, return Boolean

Fix(運算式) => 傳回運算式的整數值,小數位自動捨去.

Int(數值運算式) => 傳回整數值,若為負數則傳回小於或等於之負整數.

Rnd => 傳回0-1之間的Double類型隨機亂數值.

Math.Sign(數值) => if > 0 à 傳回1. if = 0 à 傳回0. if < 0 à 傳回 –1.

Math.Floor(數值參數) => 傳回等於或小於數值參數的最大整數. Floor值.

Math.Ceiling(數值參數) => 傳回Ceiling值.

Math.Round(數值參數) => 四捨五入傳回整數值.

Math.Abs(數值參數) => 傳回絕對值.

Math.Squrt(數值參數) => 傳回平方根.

Math.Pow(數值參數,n次方) => 傳回數值參數,n次方的值.

Math.Max(數值一,數值二) => 傳回較大值.

Math.Min(數值一,數值二) => 傳回較小值.

FormatCurrency(數值參數,小數點位數,小數點前是否補0,負值是否加小括號)

n 小數位數: 設定小數位要幾位,其餘四捨五入.

n 小數點前是否補0: -1 means YES; 0 means NO; -2 means Default.

n 負值是否加小括號: -1 means YES; 0 means NO; -2 means Default.

n EX: Response.Write(FormatCurrency(-1234.3567,2,-1,-1)) => (NT$1,234.36)

FormatNumber(數值參數,小數點位數,小數點前是否補0,負值是否加小括號)

無貨幣符號,其餘同FormatCurrent

string.Format 格式參數

{0:d} YY-MM-DD
{0:p} 百分比00.00%
{0:N2} 12.68
{0:N0} 13
{0:c2} $12.68
{0:d} 3/23/2003
{0:T} 12:00:00 AM
{0:男;;女}

DataGrid-數據格式設置表達式

數據格式設置表達式
.NET Framework 格式設置表達式,它在數據顯示在列中之前先應用于數據。此表達式由可選靜態文本和用以下格式表示的格式說明符組成:
{0:format specifier}

零是參數索引,它指示列中要格式化的數據元素;因此,通常用零來指示第一個(且唯一的)元素。format specifier 前面有一個冒號 (:),它由一個或多個字母組成,指示如何格式化數據。可以使用的格式說明符取決于要格式化的數據類型:日期、數字或其他類型。下表顯示了不同數據類型的格式設置表達式的示例。有關格式設置表達式的更多信息,請參見格式化類型。

Price: {0:C}
numeric/decimal
顯示“Price:”,后跟以貨幣格式表示的數字。貨幣格式取決于通過 Page 指令或 Web.config 文件中的區域性屬性指定的區域性設置。

{0:D4}
integer(不能和小數一起使用。)
在由零填充的四個字符寬的字段中顯示整數。

{0:N2}%
numeric
顯示精確到小數點后兩位的數字,后跟“%”。

{0:000.0}
numeric/decimal
四舍五入到小數點后一位的數字。不到三位的數字用零填充。

{0:D}
date/datetime
長日期格式(“Thursday, August 06, 1996”)。日期格式取決于頁或 Web.config 文件的區域性設置。

{0:d}
date/datetime

短日期格式(“12/31/99”)。
{0:yy-MM-dd}

date/datetime

用數字的年-月-日表示的日期(96-08-06)。

2006-02-22 | asp.net數據格式的Format– DataFormatString

我們在呈現數據的時候,不要將未經修飾過的數據呈現給使用者。例如金額一萬元,如果我們直接顯示「10000」,可能會導致使用者看成一千或十萬,造成使用者閱讀數據上的困擾。若我們將一萬元潤飾后輸出為「NT$10,000」,不但讓使比較好閱讀,也會讓使用者減少犯錯的機會。
下列畫面為潤飾過的結果:
上述數據除了將DataGrid Web 控件以顏色來區隔記錄外,最主要將日期、單價以及小計這三個計字段的數據修飾的更容易閱讀。要修飾字段的輸出,只要設定字段的DataFormatString 屬性即可;其使用語法如下:

DataFormatString=”{0:格式字符串}”

我們知道在DataFormatString 中的 {0} 表示數據本身,而在冒號后面的格式字符串代表所們希望數據顯示的格式;另外在指定的格式符號后可以指定小數所要顯示的位數。例如原來的數據為「12.34」,若格式設定為 {0:N1},則輸出為「12.3」。其常用的數值格式如下表所示:

格式字符串 資料 結果
“{0:C}” 12345.6789 $12,345.68
“{0:C}” -12345.6789 ($12,345.68)
“{0:D}” 12345 12345
“{0:D8}” 12345 00012345
“{0:E}” 12345.6789 1234568E+004
“{0:E10}” 12345.6789 1.2345678900E+004
“{0:F}” 12345.6789 12345.68
“{0:F0}” 12345.6789 12346
“{0:G}” 12345.6789 12345.6789
“{0:G7}” 123456789 1.234568E8
“{0:N}” 12345.6789 12,345.68
“{0:N4}” 123456789 123,456,789.0000
“Total: {0:C}” 12345.6789 Total: $12345.68

其常用的日期格式如下表所示:

格式 說明 輸出格式
d 精簡日期格式 MM/dd/yyyy
D 詳細日期格式 dddd, MMMM dd, yyyy
f 完整格式 (long date + short time) dddd, MMMM dd, yyyy HH:mm
F
完整日期時間格式
(long date + long time)
dddd, MMMM dd, yyyy HH:mm:ss
g 一般格式 (short date + short time) MM/dd/yyyy HH:mm
G 一般格式 (short date + long time) MM/dd/yyyy HH:mm:ss
m,M 月日格式 MMMM dd
s 適中日期時間格式 yyyy-MM-dd HH:mm:ss
t 精簡時間格式 HH:mm
T 詳細時間格式 HH:mm:ss

string.format格式結果

String.Format

(C) Currency: . . . . . . . . ($123.00)

(D) Decimal:. . . . . . . . . -123

(E) Scientific: . . . . . . . -1.234500E+002

(F) Fixed point:. . . . . . . -123.45

(G) General:. . . . . . . . . -123

(N) Number: . . . . . . . . . -123.00

(P) Percent:. . . . . . . . . -12,345.00 %

(R) Round-trip: . . . . . . . -123.45

(X) Hexadecimal:. . . . . . . FFFFFF85

(d) Short date: . . . . . . . 6/26/2004

(D) Long date:. . . . . . . . Saturday, June 26, 2004

(t) Short time: . . . . . . . 8:11 PM

(T) Long time:. . . . . . . . 8:11:04 PM

(f) Full date/short time: . . Saturday, June 26, 2004 8:11 PM

(F) Full date/long time:. . . Saturday, June 26, 2004 8:11:04 PM

(g) General date/short time:. 6/26/2004 8:11 PM

(G) General date/long time: . 6/26/2004 8:11:04 PM

(M) Month:. . . . . . . . . . June 26

(R) RFC1123:. . . . . . . . . Sat, 26 Jun 2004 20:11:04 GMT

(s) Sortable: . . . . . . . . 2004-06-26T20:11:04

(u) Universal sortable: . . . 2004-06-26 20:11:04Z (invariant)

(U) Universal sortable: . . . Sunday, June 27, 2004 3:11:04 AM

(Y) Year: . . . . . . . . . . June, 2004

(G) General:. . . . . . . . . Green

(F) Flags:. . . . . . . . . . Green (flags or integer)

(D) Decimal number: . . . . . 3

(X) Hexadecimal:. . . . . . . 00000003

說明:
String.Format
將指定的 String 中的每個格式項替換為相應對象的值的文本等效項。

例子:

int iVisit = 100;
string szName = “Jackfled”;
Response.Write(String.Format(“您的帳號是:{0} 。訪問了 {1} 次.”, szName, iVisit));

2010年7月20日 星期二

VB.net 連結 Access 語法

可分為兩種,一種是取得資料庫裡面的資料

' 資料庫的路徑
Dim strDbCon As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=coolking_music.mdb"

Dim objCon As OleDbConnection = New OleDbConnection(strDbCon)
objCon.Open()

' SQL語法
Dim objCmd As OleDbCommand = New OleDbCommand("SELECT * FROM song", objCon)

Dim objDataReader As OleDbDataReader = objCmd.ExecuteReader()

Dim out As String

' 讀取singer欄位的值
While objDataReader.Read()
out += objDataReader.Item("singer")
End While

' 關閉資料庫的連結
objDataReader.Close()
objCon.Close()

Label1.Text = out
 
另一種是顯示在DataGridView上
 
' 資料庫的路徑
Dim strDbCon As String = "Provider=Microsoft.Jet.Oledb.4.0;Data source=coolking_music.mdb"

Dim objCon As OleDbConnection = New OleDbConnection(strDbCon)
objCon.Open()

' SQL語法
Dim adp1 As OleDbDataAdapter = New OleDbDataAdapter("select * from song", objCon)

' 將查詢結果放到記憶體set1上的"song"表格內
Dim set1 As DataSet = New DataSet
adp1.Fill(set1, "song")

' 將記憶體的資料集合存放到視窗畫面上的DataGridView上
DataGridView1.DataSource = set1.Tables("song")

' 關閉資料庫的連結
objCon.Close()

利用VB.net 寄信

' 兩個收件人:GetMail1@gmail.com和GetMail2@gmail.com
Dim To_Address As String = "GetMail1@gmail.com;GetMail2@gmail.com"

' 設定SMTPserver
Dim SMTP_Server As New Mail.SmtpClient("msa.hinet.net")
Dim Mailmsg As New System.Net.Mail.MailMessage
Dim MailBodyHtml As String
 
' 設定一個信件的附檔
Dim mail_attachment As New System.Net.Mail.Attachment("Z:\Picutre\nic.jpg")
 
Mailmsg.IsBodyHtml = True ' 為html內容格式

' 此信的寄件人
Mailmsg.From = New Net.Mail.MailAddress("Send@msa.hinet.net", "寄件人")
Mailmsg.Subject = "主旨"
MailBodyHtml = "Mail Message First"
MailBodyHtml &= "Mail Message Second"
Mailmsg.Body = MailBodyHtml
 
' 把附檔加入到Mail
Mailmsg.Attachments.Add(mail_attachment)
 
' 將字串裡的;分為多個收件人
For Each MA As String In To_Address.Split(";")
Mailmsg.To.Add(New Net.Mail.MailAddress(MA, "收件人"))
Next
 
' 密件副本收件人
Mailmsg.Bcc.Add(New Net.Mail.MailAddress("GetMail3@gmail.com", "密件副本"))
Mailmsg.Priority = Net.Mail.MailPriority.High
 
' Smtp(Server) 的帳號與密碼
SMTP_Server.Credentials = New System.Net.NetworkCredential("ID", "PW")

SMTP_Server.Send(Mailmsg)

利用 VB.net 取得本機 IP

Imports System.Net.Dns
 


Public Function GetIPaddress() As String
Try
Dim ipEntry As System.Net.IPHostEntry = GetHostByName(Environment.MachineName)
Dim IpAddr As System.Net.IPAddress() = ipEntry.AddressList
 


GetIPaddress = IpAddr(0).ToString
Catch ex As Exception
GetIPaddress = "無法取得IP"
End Try
End Function

C# 設定網路介面卡組態 ( IP , SubnetMask , Gateway , DNS )

強力鎯頭 の VB 部落
using System.Management; // System.Management 命名空間

using System.Collections; // System.Collections 命名空間



namespace Win32_NetworkAdapterConfiguration

{

public partial class Form1 : Form

{



ArrayList AryLst = new ArrayList(); // ArrayList 類別

ManagementObject objCls; // ManagementObject 類別 , 表示 WMI 執行個體。

string strCls = "Win32_NetworkAdapterConfiguration"; // WMI 名稱空間 ( Namespace )

string strNS = "root\\CIMV2"; // WMI 類別 (Class)

string strIndex; // 用來記錄網路介面卡 Index



Public Form1()

{

InitializeComponent();

}



private void Form1_Load(object sender, EventArgs e)

{

GetAdtInfo(); // 呼叫 GetAdtInfo 程序來取得網路介面卡資訊

}



private void GetAdtInfo()

{

// 指定查詢網路介面卡組態 ( IPEnabled 為 True 的 )

string strQry = "Select * from Win32_NetworkAdapterConfiguration where IPEnabled=True";



// ManagementObjectSearcher 類別 , 根據指定的查詢擷取管理物件的集合。

ManagementObjectSearcher objSc = new ManagementObjectSearcher(strQry);



// 使用 Foreach 陳述式 存取集合類別中物件 (元素)

// Get 方法 , 叫用指定的 WMI 查詢 , 並傳回產生的集合。

foreach (ManagementObject objQry in objSc.Get())

{

// 取網路介面卡資訊

AryLst.Add(objQry["Index"]); // 將 Index 新增至 ArrayList

ComboBox.Items.Add(objQry["Description"]); // 將 Description 新增至 ComboBox

}

}



// Button1 指定 IP 位址 , 子網路遮罩 , 預設閘道 , DNS 伺服器

private void button1_Click(object sender, EventArgs e)

{

string strIP = "192.168.1.3"; // IP 位址

string strSubmask = "255.255.255.0"; // 子網路遮罩

string strGateway = "192.168.1.1"; // 預設閘道

string strDNS1 = "168.95.1.1"; // 慣用 DNS 伺服器

string strDNS2 = "168.95.192.1"; // 其他 DNS 伺服器



// 呼叫 SetNetCfg 程序 , 設定網路介面卡組態

SetNetCfg(strIP, strSubmask, strGateway, strDNS1, strDNS2);

}



public void SetNetCfg(string strIP, string strSubmask, string strGateway, string strDNS1, string strDNS2)

{

// 建立 ManagementObject 物件 ( Scope , Path , options )

objCls = new ManagementObject(strNS, strCls + ".INDEX=" + strIndex, null);



ManagementBaseObject objInPara; // 宣告管理物件類別的基本類別



objInPara = objCls.GetMethodParameters("EnableStatic");

objInPara["IPAddress"] = new string[] { strIP }; // 設定 "IP" 屬性

objInPara["SubnetMask"] = new string[] { strSubmask }; // 設定 "子網路遮罩" 屬性

objCls.InvokeMethod("EnableStatic", objInPara, null);



objInPara = objCls.GetMethodParameters("SetGateways");

objInPara["DefaultIPGateway"] = new string[] { strGateway }; // 設定 "Gateway" 屬性

objCls.InvokeMethod("SetGateways", objInPara, null);



objInPara = objCls.GetMethodParameters("SetDNSServerSearchOrder");

objInPara["DNSServerSearchOrder"] = new string[] { strDNS1, strDNS2 }; // 設定 "DNS" 屬性

objCls.InvokeMethod("SetDNSServerSearchOrder", objInPara, null);



// GetMethodParameters 方法 : 用來取得 SetDNSServerSearchOrder 參數清單。

// InvokeMethod 方法 : 在物件上叫用方法。

}



// Button2 使用 DHCP 自動取得 IP

private void button2_Click(object sender, EventArgs e)

{

SetAuto(); // 呼叫 SetAuto 程序 , 設定網路介面卡組態

}



public void SetAuto()

{

// 建立 ManagementObject 物件 ( Scope , Path , options )

objCls = new ManagementObject(strNS, strCls + ".INDEX=" + strIndex, null);



// InvokeMethod 方法 : 在物件上叫用方法。

objCls.InvokeMethod("EnableDHCP", null); // 設定自動取得 IP

objCls.InvokeMethod("ReleaseDHCPLease", null); // 釋放 IP

objCls.InvokeMethod("RenewDHCPLease", null); // 重新取得 IP

}



private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)

{

// 取得使用者選取的網路介面卡 Index

strIndex = (ComboBox.SelectedIndex + 1).ToString();

}



}

}

如何設定TextBox中的scrollbar 自動滾動到最底端

textbox1.SelectionStart =textbox1.Text.Length
textbox1.ScrollToCaret()

---
這要控制:自動滾動到最底端,不可放在form_load 內;那將會失效

Crystal Reports 和sql-server共同進行報表的開發

Crystal Reports 和sql-server共同進行報表的開發

1:Crystal Reports功能自述
Crystal Reports 用於處理數據庫,幫助用戶分析和解釋重要信息。使用 Crystal Reports 可以方便地創建簡單報表,同時它也提供了創建複雜或專用的報表所需的整套工具。

創建所能想像的任何報表
Crystal Reports 幾乎可以從任何數據源生成您需要的報表。內置報表專家在您生成報表和完成一般的報表任務過程中,會一步一步地指導您進行操作。報表專家通過公式、交叉表、子報表和設置條件格式幫助表現數據的實際意義,揭示可能被隱藏掉的重要關係。如果文字和數字確實不夠充分,則用地理地圖和圖形進行形象的信息交流。

將報表擴展到 Web
Crystal Reports 的靈活性並未停留在創建報表這一功能上 ?您可以用各種各樣的格式發佈報表,包括用 Microsoft 的 Word 和Excel 發佈、通過電子郵件甚至 Web 發佈。高級的 Web 報表功能允許工作組中的其他成員在他們自己的 Web 瀏覽器中查看或更新共享報表。

將報表並入應用程序
通過將 Crystal Reports 的報表處理功能整合到自己的數據庫應用程序中,應用程序和 Web 開發人員可以節省開發時間並滿足用戶的需求。Crystal Reports 支持大多數流行的開發語言,可以方便地在任何應用程序中添加報表。

不論您是 IT 行業的站點管理員,還是營銷推廣經理,也無論您是金融業的數據庫管理員還是 CEO,Crystal Reports 都堪稱是一個功能強大的工具,它可以幫助每一個人分析、解釋重要信息。

2:Crystal Reports和Sql-server結合
Crystal雖然提供了強大的報表功能,但是對於複雜的邏輯運算,卻是很難實現。但是,Crystal中可以像添加表一樣添加存儲過程,這就給我們的複雜運算提供了簡便的處理方法。

3:例子
這是我們給國航公司it服務項目做的報表的sql-server存儲過程部分。(歡迎大家共同討論)
A:每個員工的處理故障完成數、總數
fgw_proc1.txt

--fgw_proc1 處理故障完成數、總數
CREATE PROCEDURE [AHD].[fgw_proc1](@開始時間 datetime , @結束時間 datetime)
AS
DECLARE @begin int , @end int /*轉時間*/
exec fgw_util1 @開始時間, @begin output
exec fgw_util1 @結束時間, @end output


DECLARE @userid int, @handled float, @total float

CREATE TABLE #temp_proc1
(
userid int,
handled float,
total float
)

DECLARE cur_ctct CURSOR FOR SELECT id FROM AHD.AHD.ctct --取所有的用戶id
OPEN cur_ctct
FETCH cur_ctct INTO @userid
WHILE @@FETCH_STATUS = 0
BEGIN
--get @handle through exec fgw_proc2
EXEC fgw_proc1_1 @userid , @begin , @end , @handled output , @total output /*call下個存儲過程,得到某個用戶的解決數、接觸故障數*/
INSERT INTO #temp_proc1 VALUES (@userid , @handled , @total) /*將用戶信息插入臨時表*/
FETCH NEXT FROM cur_ctct INTO @userid /*記錄下移*/
END
CLOSE cur_ctct
DEALLOCATE cur_ctct
SELECT * FROM #temp_proc1 /*生成結束集*/
DROP TABLE #temp_proc1 /*釋放*/
GO

fgw_proc1_1.txt

--fgw_proc1_1
CREATE PROCEDURE [AHD].[fgw_proc1_1](@userid int , @begin int , @end int , @handled float OUTPUT , @total float OUTPUT)
AS

SET @handled = 0
SET @total = 0
DECLARE @cr_id int, @zh_id int, @status char(12), @to_status char(12), @cnt int, @open_date int
--handled /*計算此人的處理完成故障數*/
DECLARE cur11_1 CURSOR FOR SELECT AHD.call_req.id AS cr_id, AHD.ztr_his.id AS zh_id, AHD.call_req.status, AHD.ztr_his.to_status, AHD.ztr_his.to_cnt AS cnt, AHD.call_req.open_date FROM AHD.call_req LEFT OUTER JOIN AHD.ztr_his ON AHD.call_req.persid = AHD.ztr_his.call_req_id WHERE AHD.call_req.type='I' AND (AHD.call_req.status IN ('CL', 'TTPC')) AND (AHD.ztr_his.to_status IN ('L1WIP', 'L2WIP', 'ICP', 'SRBYL1', 'SRBYL2', 'NCCBYL1', 'NCCBYL2', 'CRBYL1', 'CRBYL2')) AND AHD.call_req.open_date>@begin AND AHD.call_req.open_date<@end AND AHD.ztr_his.to_cnt = @userid
OPEN cur11_1
FETCH cur11_1 INTO @cr_id, @zh_id, @status, @to_status, @cnt, @open_date /*事件id,歷史id,狀態,處理人,打開時間取所需要的值*/
WHILE @@FETCH_STATUS = 0 /*循環每一個記錄*/
BEGIN
DECLARE @count2 int /*每個事件單在歷史記錄中有多少條*/
DECLARE cur11_2 CURSOR FOR SELECT count(*) FROM AHD.call_req LEFT OUTER JOIN AHD.ztr_his ON AHD.call_req.persid = AHD.ztr_his.call_req_id WHERE AHD.call_req.type='I' AND (AHD.call_req.status IN ('CL', 'TTPC')) AND (AHD.ztr_his.to_status IN ('L1WIP', 'L2WIP', 'ICP', 'SRBYL1', 'SRBYL2', 'NCCBYL1', 'NCCBYL2', 'CRBYL1', 'CRBYL2')) AND (AHD.call_req.open_date>@begin) AND (AHD.call_req.open_date<@end) AND (AHD.call_req.id = @cr_id)
OPEN cur11_2
FETCH cur11_2 INTO @count2
CLOSE cur11_2
DEALLOCATE cur11_2
IF @count2 <> 0
SET @handled = @handled + 1.0 / @count2 /*此人的處理完成數*/
FETCH NEXT FROM cur11_1 INTO @cr_id, @zh_id, @status, @to_status, @cnt, @open_date /*循環記錄*/
END
CLOSE cur11_1
DEALLOCATE cur11_1

--total /*計算此人的處理故障數*/
DECLARE cur11_3 CURSOR FOR SELECT count(distinct(AHD.call_req.id)) FROM AHD.call_req LEFT OUTER JOIN AHD.ztr_his ON AHD.call_req.persid = AHD.ztr_his.call_req_id WHERE AHD.call_req.type='I' AND (AHD.call_req.open_date>@begin AND AHD.call_req.open_date<@end) AND (AHD.ztr_his.to_cnt = @userid) /*取此人所有單*/

OPEN cur11_3
FETCH cur11_3 INTO @total /*總故障數*/
CLOSE cur11_3
DEALLOCATE cur11_3

--SELECT @handled
--declare @handled float,@total float
--exec fgw_proc1_1 400115,1,1111111111,@handled output ,@total output
--print @handled
--print @total
GO

B:每個員工的響應達標數、響應總數
fgw_proc2.txt
--fgw_proc2 響應達標數、響應總數
CREATE PROCEDURE [AHD].[fgw_proc2](@開始時間 datetime , @結束時間 datetime)
AS
DECLARE @begin int , @end int
exec fgw_util1 @開始時間, @begin output
exec fgw_util1 @結束時間, @end output

DECLARE @cr_id int, @zh_id int, @cnt int, @sym char(30), @time_stamp int, @isOK int , @userid int , @handled int , @total int
DECLARE @call_req_id char(30)

CREATE TABLE #temp_proc2 /* 響應達標數、響應總數*/
(
userid int,
handled2 int,
total2 int
)

CREATE TABLE #temp_proc2_1 /* 事件單為op的記錄*/
(
cr_id int,
zh_id int,
cnt int,
isOK int
)

--initialize #temp_proc2_1 /*已經op的單,是否響應達標,返回處理人*/
DECLARE cur2_1 CURSOR FOR SELECT zh.call_req_id,zh.id,zh.to_cnt,sd.sym,zh.time_stamp FROM AHD.AHD.call_req as cr LEFT OUTER JOIN AHD.AHD.ztr_his as zh ON cr.persid=zh.call_req_id LEFT OUTER JOIN AHD.AHD.srv_desc as sd ON cr.support_lev=sd.code WHERE cr.type='I' and cr.open_date>@begin and cr.open_date<@end and (zh.to_status='ASTOL1' OR zh.to_status='ASTOL2')
OPEN cur2_1
FETCH cur2_1 INTO @call_req_id, @zh_id, @cnt, @sym, @time_stamp /*事件單id,歷史單id,人員,服務級別,op狀態的時間*/
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC fgw_proc2_1 @call_req_id , @sym , @time_stamp , @isOK output
INSERT INTO #temp_proc2_1 VALUES (@cr_id , @zh_id , @cnt , @isOK)
FETCH NEXT FROM cur2_1 INTO @call_req_id, @zh_id, @cnt, @sym, @time_stamp
END
CLOSE cur2_1
DEALLOCATE cur2_1

--initialize #temp_proc2
DECLARE cur2_2 CURSOR FOR SELECT id FROM AHD.AHD.ctct
OPEN cur2_2
FETCH cur2_2 INTO @userid
WHILE @@FETCH_STATUS = 0
BEGIN
--get @total /*所有的已響應的單*/
DECLARE cur2_3 CURSOR FOR SELECT count(*) FROM #temp_proc2_1 WHERE cnt = @userid
OPEN cur2_3
FETCH cur2_3 INTO @total
CLOSE cur2_3
DEALLOCATE cur2_3

--get @handled /*所有的已響應的單,並達標的單*/
DECLARE cur2_4 CURSOR FOR SELECT count(*) FROM #temp_proc2_1 WHERE cnt = @userid AND isOK=1
OPEN cur2_4
FETCH cur2_4 INTO @handled
CLOSE cur2_4
DEALLOCATE cur2_4

INSERT INTO #temp_proc2 VALUES (@userid , @handled , @total)
FETCH NEXT FROM cur2_2 INTO @userid
END
CLOSE cur2_2
DEALLOCATE cur2_2
DROP TABLE #temp_proc2_1
SELECT * FROM #temp_proc2
DROP TABLE #temp_proc2
GO

fgw_proc2_1.txt
--fgw_proc2_1
CREATE PROCEDURE [AHD].[fgw_proc2_1](@call_req_id char(30) , @level char(30) , @time_stamp int , @isOK int OUTPUT)
AS
SET NOCOUNT ON
SET @isOK = 0

DECLARE cur_zh CURSOR FOR SELECT time_stamp FROM AHD.AHD.ztr_his WHERE call_req_id = @call_req_id and to_status in ('L1WIP','L2WIP') and time_stamp>@time_stamp
OPEN cur_zh
DECLARE @time_stamp1 int
SET @time_stamp1=0

FETCH cur_zh INTO @time_stamp1
IF (@time_stamp1 is not null) and (@time_stamp1<>0)
BEGIN
IF CHARINDEX('一級', @level) IS NOT NULL AND CHARINDEX('一級', @level)<>0
BEGIN
if @time_stamp1 - @time_stamp <600
SET @isOK=1
END
ELSE IF CHARINDEX('二級', @level) IS NOT NULL AND CHARINDEX('二級', @level)<>0
BEGIN
if @time_stamp1 - @time_stamp <1800
SET @isOK=1
END
ELSE IF CHARINDEX('三級', @level) IS NOT NULL AND CHARINDEX('三級', @level)<>0
BEGIN
if @time_stamp1 - @time_stamp <1800
SET @isOK=1
END
ELSE IF CHARINDEX('四級', @level) IS NOT NULL AND CHARINDEX('四級', @level)<>0
BEGIN
if @time_stamp1 - @time_stamp <1800
SET @isOK=1
END
END

CLOSE cur_zh
DEALLOCATE cur_zh
--SELECT @isOK, @time_stamp1
GO

C:每個員工的處理時限達標數,總數
fgw_proc3.txt
--fgw_proc3
CREATE PROCEDURE fgw_proc3(@開始時間 datetime , @結束時間 datetime)
AS
/*時間轉換*/
DECLARE @begin int , @end int
exec fgw_util1 @開始時間, @begin output
exec fgw_util1 @結束時間, @end output

DECLARE @cr_id int, @zh_id int, @cnt int, @sym char(30), @time_stamp int, @isOK int , @userid int , @handled int , @total int

CREATE TABLE #temp_proc3
(
userid int,
handled2 int,
total2 int
)

DECLARE cur3_2 CURSOR FOR SELECT id FROM AHD.AHD.ctct
OPEN cur3_2
FETCH cur3_2 INTO @userid
WHILE @@FETCH_STATUS = 0
BEGIN
--get @handled
DECLARE cur3_4 CURSOR FOR SELECT distinct(cr.id) FROM AHD.AHD.call_req as cr LEFT OUTER JOIN AHD.AHD.ztr_his as zh ON cr.persid=zh.call_req_id WHERE cr.type='I' and cr.open_date>@begin and cr.open_date<@end and zh.to_cnt = @userid and cr.sla_violation=0
OPEN cur3_4
SET @handled = @@CURSOR_ROWS
CLOSE cur3_4
DEALLOCATE cur3_4

--get @total
DECLARE cur3_5 CURSOR FOR SELECT distinct(cr.id) FROM AHD.AHD.call_req as cr LEFT OUTER JOIN AHD.AHD.ztr_his as zh ON cr.persid=zh.call_req_id WHERE cr.type='I' and cr.open_date>@begin and cr.open_date<@end and zh.to_cnt = @userid
OPEN cur3_5
SET @total = @@CURSOR_ROWS
CLOSE cur3_5
DEALLOCATE cur3_5

INSERT INTO #temp_proc3 VALUES (@userid , @handled , @total)
FETCH NEXT FROM cur3_2 INTO @userid
END
CLOSE cur3_2
DEALLOCATE cur3_2
SELECT * FROM #temp_proc3
DROP TABLE #temp_proc3

D:將日期格式轉換成整型
fgw_util1.txt

--fgw_util1
CREATE PROCEDURE [AHD].[fgw_util1] (@time datetime, @seconds int output)
AS
set @seconds=datediff(ss,'1970-01-01 00:00:00', @time)
GO

關於 Crystal Report 使用程式填入資料

今天有一張報表,其中包含子報表,子報表的資料不是從資料庫撈而是使用程式填入,程式碼如下:
'載入報表
Dim rptdoc As ReportDocument = CRUtil.LoadReport("C:\ReportFilePath.rpt")
'設定報表參數
CRUtil.SetParameters(rptdoc, "@P1", "abc")
CRUtil.SetParameters(rptdoc, "@P2", 1)
'設定報表資料來源連接資訊
CRUtil.SetConnection(rptdoc, Me.ReportConnectionInfo())
'設定報表資料內容
Dim dtl As DataTable = Me.GetSubReportData()
rptdoc.Subreports("SubReport.rpt").Database.Tables("SubReport").SetDataSource(dtl)


結果發現在執行顯示報表時 CrystalReportViewer 會跳出輸入參數的畫面,
查了好久查不出原因。


後來發現是因為當我將資料直接填到子報表的時候,報表參數的值會被清除@@,
將程式碼順序對掉後就可以了。
對掉後的程式碼:
'載入報表
Dim rptdoc As ReportDocument = CRUtil.LoadReport("C:\ReportFilePath.rpt")
'設定報表資料內容
Dim dtl As DataTable = Me.GetSubReportData()
rptdoc.Subreports("SubReport.rpt").Database.Tables("SubReport").SetDataSource(dtl)
'設定報表參數
CRUtil.SetParameters(rptdoc, "@P1", "abc")
CRUtil.SetParameters(rptdoc, "@P2", 1)
'設定報表資料來源連接資訊
CRUtil.SetConnection(rptdoc, Me.ReportConnectionInfo())

Crystal Report 子報表

參考  http://community.csdn.net/Expert/topic/3463/3463941.xml?temp=.3613092

問題已解決,我把原作者用C#寫的代碼改成了vb.net,與大家共分享

在page_load中加載如下代碼,一切正常


Dim prtTran As New DataAccess.Transport


'設置主表
Dim dsTran As DataSet = prtTran.TraGetByTraPKID(curr_TraPKID)
Dim prtTranTable As DataTable = dsTran.Tables(0)
'dsTran.Tables.Remove(prtTranTable)
Dim rptTran As New crTran
rptTran.SetDataSource(prtTranTable)

'設置子表()
Dim dsTranDetail As DataSet = prtTran.TrdGetByTraPKID(curr_TraPKID)
Dim prtTranDetailTable As DataTable = dsTranDetail.Tables(0)
'dsTranDetail.Tables.Remove(prtTranDetailTable)

Dim rptTranDetail As New crTranDetail
rptTranDetail.SetDataSource(prtTranDetailTable)


'設置登錄信息

Dim crSections As CrystalDecisions.CrystalReports.Engine.Sections
Dim crReportObjects As CrystalDecisions.CrystalReports.Engine.ReportObjects
Dim crSubreportObject As CrystalDecisions.CrystalReports.Engine.SubreportObject
Dim crDatabase As CrystalDecisions.CrystalReports.Engine.Database
Dim crTables As CrystalDecisions.CrystalReports.Engine.Tables
Dim crConnectioninfo As CrystalDecisions.Shared.ConnectionInfo = New CrystalDecisions.Shared.ConnectionInfo
Dim crSubreportDocument As ReportDocument

Dim tbl As CrystalDecisions.CrystalReports.Engine.Table
Dim logOnInfo As New TableLogOnInfo

'設置logOnInfo參數
For Each tbl In rptTran.Database.Tables

logOnInfo = tbl.LogOnInfo
logOnInfo.ConnectionInfo.ServerName = "localhost "
logOnInfo.ConnectionInfo.DatabaseName = "your db "
logOnInfo.ConnectionInfo.UserID = "sa "
logOnInfo.ConnectionInfo.Password = "yourpassword "
tbl.ApplyLogOnInfo(logOnInfo)
Next

crSections = rptTran.ReportDefinition.Sections
Dim crSection As Section
For Each crSection In crSections

crReportObjects = crSection.ReportObjects
Dim crReportObject As ReportObject
For Each crReportObject In crReportObjects

If (crReportObject.Kind = ReportObjectKind.SubreportObject) Then

crSubreportObject = CType(crReportObject, SubreportObject)
crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName)
crDatabase = crSubreportDocument.Database
crTables = crDatabase.Tables

Dim crTable As CrystalDecisions.CrystalReports.Engine.Table
For Each crTable In crTables

crConnectioninfo.ServerName = "Localhost "
crConnectioninfo.UserID = "sa "
crConnectioninfo.Password = "your_password "
crConnectioninfo.DatabaseName = "your_db "
logOnInfo = crTable.LogOnInfo
logOnInfo.ConnectionInfo = crConnectioninfo
crTable.ApplyLogOnInfo(logOnInfo)
Next
End If
Next
Next


crvTransport.ReportSource = rptTran
crvTransport.Zoom(2)


prtTranDetailTable.DataSet.Dispose()
prtTranTable.DataSet.Dispose()

2010年7月19日 星期一

連結 crystal report 相關文章

有很多 crystal report 較進階的技巧文章

為你的水晶報表裝載本地圖片

為你的水晶報表裝載本地圖片【轉】
本文為解答該貼所做:http://topic.csdn.net/u/20090524/15/911fd15a-32c6-4be9-9aa1-3ee95365e7e3.html
並沒有什麼新內容,主要是如何讀取本地圖片顯示在報表中。
如果是CR XI及以上版本,可以用更簡便的方法,參考:水晶報表圖片動態加載的另一種簡單方案
本文的方法是:水晶報表中如何動態加載圖片(圖片文件版本及數據庫版本) 中的圖片文件版本。
本文適用於VS2003及VS2005自帶版本的水晶報表,當然同樣適用於CR XI及以上版本,就是煩了點。
本文使用VS2005及自帶版本的水晶報表。

在這裡,我把命題重新提煉一下:
已經有一個完整的報表,現在報表需要加載一個本地磁盤圖片做為logo。報表中的logo隨著本地圖片的變化自動變化。
一般我們通過插入一個pictureobject來插入磁盤圖片,但是插入後,圖片就成為報表的一份,達不到變化的目的。

1:首先我們已經有了一個單表的完整水晶報表應用




2:為了能掛接我們的本地圖片,在dataset裡新建立一個表mylogo。
裡面放上兩個字段,字段類型為System.Byte[]或System.sByte[]
注意,默認類型裡只有System.Byte和System.SByte,要自己輸入的。

這個mylogo就是一個中介,我們把本地圖片讀到這個表裡,水晶報表從這個表裡讀到圖片顯示。



3:在現有報表裡加入一個子報表,數據源就是這個mylogo.




把兩個字段拖到子報表上。


4:代碼段是這樣的

1 //設置數據源信息
2 DataSet1 ds1 = new DataSet1();
3 OleDbDataAdapter da = new OleDbDataAdapter();
4 String connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath ("~/app_data/test.mdb")+";";
5 OleDbConnection cn = new OleDbConnection(connstr);
6
7
8 //獲取記錄集,注意,最終獲取的記錄集需要與xsd的結構一致!
9 da = new OleDbDataAdapter("SELECT EmployeeId1 as EmployeeId,EmployeeName1 as EmployeeName From Employee1", cn);
10 da.Fill(ds1, "Employee");
11
12 //把本地圖片先寫入到數據集
13
14 //將圖片讀到stream,並轉換為byte[]
15 //圖片1
16 FileStream fs1 = new FileStream(@"c:\1.bmp", FileMode.Open, FileAccess.Read);
17 BinaryReader br1 = new BinaryReader(fs1);
18 byte[] bt1 = br1.ReadBytes((int)fs1.Length);
19 //圖片2
20 FileStream fs2 = new FileStream(@"c:\a2.jpg", FileMode.Open, FileAccess.Read);
21 BinaryReader br2 = new BinaryReader(fs2);
22 byte[] bt2 = br2.ReadBytes((int)fs2.Length);
23
24 fs1.Close();
25 fs2.Close();
26 //寫入到ds1中(僅1行)
27 ds1.myLogo.AddmyLogoRow(bt1, bt2);
28
29
30 //以上為數據部分,與報表無關
31 //-----------------------------------------------------------
32 //以下為報表部分
33
34 //使用報表對像加載報表
35
36 string reportPath = Server.MapPath("~/app_data/crystalreport1.rpt");
37 myReport.Load(reportPath);
38 //綁定數據集,注意,一個報表用一個數據集。
39 myReport.SetDataSource(ds1);
40 CrystalReportViewer1.ReportSource = myReport;


5:效果是這樣的

給水晶報表傳值的兩種方式

給水晶報表傳值的兩種方式
在設計水晶報表的過程中,對於傳值給水晶報表,發現網上很難找到比較全的資料,所以特對此內容進行一下總結,供大家分享.

如果沒有為水晶報表傳值,其顯示的結果通常為對應數據庫表的所有記錄,那麼怎樣才能讓水晶報表只顯示用戶需要的數據呢?這就是給水晶報表傳值的問題.解決這個問題有兩種方式:給水晶報表傳遞查詢的值和給水晶報表傳遞用戶查詢的結果.

1、給水晶報表傳遞查詢值
要實現給水晶報表傳遞查詢值,首先在設計報表時,需要在Parameter Fields中添加參數字段(方法為:在Field Explorer面板中,鼠標在Parameter Fields上游擊,選擇New,自己取一個名字.比如我們數據庫中存在一個'日期'的字段,我們添加一個Month用來查詢滿足Month的值).然後點擊菜單項Crystal Reports->Report->Selection Formula->Record,彈出Formula Workshop對話框,編輯查詢語句如:Month({tbl_SellMain.日期})={?Month}.{tbl_SellMain.日期}可以通過連接中雙擊日期字段得到.這樣水晶報表設計就完成了.Main Report Preview可以查看報表的顯示結果,根據提示輸入Month的值後,可以看到顯示結果中只有滿足用戶輸入條件的結果了.

如果在C#中不添加任何代碼,在每次顯示報表時,都會提示輸入Month的信息,那麼怎樣在程序中傳入Month的值呢?

在C#中添加如下代碼.
using CrystalDecisions.Shared;
//指定報表對應的報表文件
crystalReportViewer1.ReportSource = path; //crystalReportViewer1為添加在窗體中的CrystalReportViewer.

//給報表傳值,獲得滿足條件的查詢結果
ParameterFields paramFields = crystalReportViewer1.ParameterFieldInfo;

ParameterField paramMonth = paramFields["Month"];

ParameterValues curValues=paramCompany.CurrentValues;
ParameterDiscreteValue discreteValue = new ParameterDiscreteValue();
discreteValue.Value = 5; //5為用戶設置的查詢,此處表示查詢的月份為5月
curValues.Add(discreteValue);

crystalReportViewer1.ParameterFieldInfo = paramFields;
這樣,顯示的結果就僅為5月份的數據.

2、給水晶報表傳遞用戶查詢的結果
給水晶報表傳遞查詢結果的方式比較直觀,在報表設計時也只需要設計好要顯示的字段即可.其步驟為:通過SqlDataAdapter獲得查詢數據,然後填充到一個DataTable對像,然後用此對像填充ReportDocument對像,最後將水晶報表的ReportSource指定為此ReportDocument對像.

在C#中實現的代碼為:
//生成查詢語句
string select="select * from tbl_SellMain where";
if (txtName.Text.Trim() != "")
select += " 公司名稱='" + txtName.Text.Trim() + "' and";
select += " Year(日期)=" + cmbYear.Text + " and";
select += " Month(日期)=" + cmbMonth.Text;

SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=GYHR;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter(select, conn);
DataTable dt=new DataTable();
da.Fill(dt);

//這裡必須事先申明一個ReportDocument對像 Report,同時加載數據報表
ReportDocument rd = new ReportDocument();
//獲取.rpt文件真實路徑
string path;
rd.Load(path);
rd.Database.Tables[0].SetDataSource(dt); //對應報表設計的第一個數據表
crystalReportViewer1.ReportSource = rd;
//crystalReportViewer1.PrintReport(); 打印

水晶報表編程及問題總結

水晶報表編程及問題總結
1.怎麼讓組頁眉,在同一組中每一頁都顯示

插入組的時候,在公用選項頁面選中「在每個頁面上重複組頁眉」

2.如何向 CrystalReportViewer 和 ReportDocument 傳遞參數……

一、CrystalReportViewer
通過 CrystalReportViewer.ParameterFieldInfo 屬性……
1、crystalreportviewer 成員
公共實例屬性
ParameterFieldInfo(從 CrystalReportViewerbase 繼承) ParameterFields。獲取或設置參數字段集合。

二、reportdocument
通過 ReportDocument.DataDefinition.ParameterFields 屬性……
1、reportdocument 成員
公共實例屬性
DataDefinition DataDefinition。獲取 DataDefinition 對象。
2、datadefinition 成員
公共實例屬性
ParameterFields ParameterFieldDefinitions。獲取 ParameterFieldDefinitions 集合。

三、參數字段運行時自定義(crystalreportviewer)
參考:
設置參數 | Windows 窗體查看器的綁定選項 | Web 窗體查看器的綁定選項
可支持用戶在 Crystal 報表中通過參數進行輸入。這種參數有多種用途。例如:
使參數基於數據庫字段並允許用戶指定該字段的值,以便對報表中的數據進行篩選。
使用參數字段將條件格式應用於報表。
使用參數字段來定義排序順序。
下列示例說明如何在運行時通過代碼設置參數字段值。此例解釋了如何設置兩個不同的參數:第一個是多值離散參數,第二個是區域值參數。

在運行時修改參數字段

[c#]
// 聲明將參數傳遞給
//查看器控件所需的變量。
ParameterFields paramFields = new ParameterFields ();
ParameterField paramField = new ParameterField ();
ParameterDiscreteValue discreteVal = new ParameterDiscreteValue ();
ParameterRangeValue rangeVal = new ParameterRangeValue ();

// 第一個參數是具有多個值的離散參數。

// 設置參數字段的名稱,它必須
//和報表中的參數相符。
paramField.ParameterFieldName = "客戶姓名";

// 設置第一個離散值並將其傳遞給該參數。
discreteVal.Value = "AIC Childrens";
paramField.CurrentValues.Add (discreteVal);

// 設置第二個離散值並將其傳遞給該參數。
// discreteVal 變量被設置為新值,這樣,以前的設置
//就不會被覆蓋。
discreteVal = new ParameterDiscreteValue ();
discreteVal.Value = "Aruba Sport";
paramField.CurrentValues.Add (discreteVal);

// 將該參數添加到參數字段集合。
paramFields.Add (paramField);

// 第二個參數為區域值。paramField 變量
//被設置為新值,這樣,以前的設置就不會被覆蓋。
paramField = new ParameterField ();

// 設置參數字段的名稱,它必須
//和報表中的參數相符。
paramField.ParameterFieldName = "客戶 ID";

// 設置範圍的開始值和結束值並將該範圍傳遞給
//該參數。
rangeVal.StartValue = 42;
rangeVal.EndValue = 72;
paramField.CurrentValues.Add (rangeVal);

// 將第二個參數添加到參數字段集合。
paramFields.Add (paramField);

// 將參數字段集合放入查看器控件。
crystalReportViewer1.ParameterFieldInfo = paramFields;

更多資料請查看:http://www.devedu.com/develop/2005-4-8/12305/default.aspx

3.設置Crystal Report Viewer 的外觀

設置 Crystal Report Viewer 的屬性:
BestFitPage 布爾值。獲取或設置頁面視圖是大小合適還是用滾動條進行裁剪。
這個地方設為false後,設置Crystal Report Viewer 的寬度就可以去除滾動條了。
說明 :目前有兩種情況,其中在從 Web 窗體查看器進行打印時會出現問題:
BestFitPage屬性為默認值「真」(即,沒有垂直或水平滾動條),但PageZoomFactor大於 100。
BestFitPage 設置為「假」,Web 窗體查看器的高度小於報表頁的高度(即,有垂直滾動條),而查看器的寬度大於或等於報表頁的寬度(即,沒有水平滾動條)。
配合設置 Width、Height 來實現無空白和無滾動條的顯示!
DisplayGroupTree 布爾值。獲取或設置樹視圖是可見還是隱藏。
DisplayPage 布爾值。獲取或設置工具欄是可見還是隱藏。
DisplayToolbar 布爾值。獲取或設置工具欄上的轉到頁按鈕是可見還是隱藏。
PageZoomFactor Int32。獲取或設置報表的縮放因數。
SeparatePages 布爾值。獲取或設置報表頁是分開還是連接。
PageToTreeRatio Float64。設置組樹與報表視圖之間的大小比例。

4.控制工具欄的按鈕:

設置 Crystal Report Viewer 的屬性:
HasGotoPageButton 布爾值。獲取或設置轉到頁按鈕的可見性。
HasLevelUpButton 布爾值。獲取或設置工具欄上的轉到上一頁按鈕是可見還是隱藏。
HasPageNavigationButtons 布爾值。獲取或設置工具欄上的頁面導航按鈕是可見還是隱藏。
HasRefreshButton 布爾值。獲取或設置工具欄上的刷新按鈕是可見還是隱藏。
HasSearchButton 布爾值。獲取或設置工具欄上的搜索按鈕是可見還是隱藏。
HasZoomFactorList 布爾值。獲取或設置工具欄上的縮放因數列表是可見還是隱藏。

5.在 Web 頁面裡的佈局:

在「設計視圖」,修改 CrystalReportViewer 的 Width、Height 屬性。
切換到窗體的「HTML 視圖」,修改 style 屬性。
<CR:CrystalReportViewer id="CrystalReportViewer1" style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 8px" runat="server" Width="350px" Height="50px" EnableDrillDown="False" DisplayGroupTree="False"></CR:CrystalReportViewer>

6.除水晶報表的的公司LOGO

將 Crystal 公司的Logo 文件替換或刪除……
(1)如果是用 VS.NET 裡自帶的水晶報表
C:\Program Files\Microsoft Visual Studio .NET\Crystal Reports\Viewers\images\ToolBar\logo.gif
(2)如果是用水晶報表 9.2
C:\Program Files\Common Files\Crystal Decisions\2.0\crystalreportviewers\images\toolbar\crlogo.gif

7.替換水晶報表裡的各種圖標和圖片

(1)如果是用 VS.NET 裡自帶的水晶報表
C:\Program Files\Microsoft Visual Studio .NET\Crystal Reports\Viewers\images
(2)如果是用水晶報表 9.2
C:\Program Files\Common Files\Crystal Decisions\2.0\crystalreportviewers\images

8.關於打印的時候安裝插件:

在 Crystal Reports 的更新版本中,您可以使用新的 CrystalReportViewer.PrintMode 屬性來指定打印模式。其中包含兩個選擇項:ActiveX 和 PDF。
當屬性設置為PrintMode.PDF 時,報表會在WEB服務器上導出為PDF,然後以數據流傳送到瀏覽器,使用者可以利用選項,直接打印到打印機。這個選項是跨平台相容的。

當屬性設置為PrintMode.ActiveX時,ActiveX 打印控制項允許使用者將報表直接打印到本地打印機

先下載 http://support.businessobjects.com/CRforVS2005/PrintControl.cab,放到自已的服務器上。
若要在 Crystal Reports for Visual Studio 2005 網站顯示 cab 包,需將下列 xml 語句加入網站的 web.config 文件(必須加到<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">之後,也就是最前面):
<configSections>
<sectionGroup name="businessObjects">
<sectionGroup name="crystalReports">
<section name="printControl" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
</sectionGroup>
</sectionGroup>
</configSections>
<businessObjects>
<crystalReports>
<printControl>
<add key="url" value="http://192.168.88.91/PrintControl.cab"/> --這裡改為.CAB包所在地址
</printControl>
</crystalReports>
</businessObjects>

注意:只有 Internet Explorer 才會支持 ActiveX 模式。若從非 Internet Explorer 的瀏覽器 (FireFox、Safari、Mozilla 等) 打印,將會恢復到 PDF 彈出對話框。

然後在打印的頁面或直接在主窗體添加一個層,並在層中添加如下代碼(可以採用其他方式)
<object id="CrystalPrintControl" classid="CLSID:BAEE131D-290A-4541-A50A-8936F159563A"
codebase="http://192.168.88.91/printcontrol.cab" height="0px" version="10,2,0,1078"
viewastext="" width="0px">
</object>
version是版本號,如果你是其他的版本將版本號修改一下即可。

9.已達到系統管理員配置的最大報表處理作業數限制的處理

解決辦法:
具體為修改下面兩個鍵的值。
HKEY_LOCAL_MACHINE; SOFTWARE; Crystal Decisions; 10.0; Report Application
Server; InprocServer; PrintJobLimit 修改為1000
還有一個HKEY_LOCAL_MACHINE; SOFTWARE; Crystal Decisions; 10.0; Report Application
Server; Server; PrintJobLimit 也修改為1000

我發現在C:\WINDOWS\Temp這個臨時文件裡面有大量的水晶報表文件,每使用一次就會生成幾個文件,在電腦沒有重新啟動的情況下它不會被刪除,而出現大量的無用文件,在google裡面搜了一圈發現也有人碰到這樣的情況但回答的很模糊只是說要將水晶報表裝載的文檔關閉掉,從這裡可以看出出現這樣的錯誤應該是程序員人為照成的.
具體解決如下:
1.ReportDocumen實例必須為類成員

private ReportDocument prtp = new ReportDocument();

2.使用完水晶報表必須關閉文件,這樣子就不會在windows的臨時文件裡面產生.
private void Page_Unload(object sender, EventArgs e)
{
prtp.Dispose();
}
Page_Unload 事件是在頁面完全顯示的時候運行,這樣子就解決了.

水晶報表函數大全

匯總函數的條件
以下是每個匯總函數的條件列表:

布爾型條件
任何更改
更改為「是」
更改為「否」
對每個「是」
對每個「否」
對下一個「是」
對下一個「否」

日期條件
每天
每週
每兩周
每半月
每月
每季
每半年
每年

時間條件
每秒
每分鐘
每小時
上午/下午


Sum
Basic 語法和 Crystal 語法。

重載
Sum (fld)
Sum (fld, condFld)
Sum (fld, condFld, cond)
Sum (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠添加報表中出現的值。例如:

如果銷售報表包含一個顯示每張訂單金額的字段,則可以計算報表上出現的所有訂單的總和(總計和)。
如果對訂單進行分組(例如,按訂單所來自的省份對其分組),則可以計算每組訂單金額的總和(在本例中,為每個省)。
如果將訂單按日期或布爾值分組(例如,對訂單按其發出的月份進行分組),則可以根據日期字段或布爾字段中的特定變化來計算每組訂單金額的總和(在本例中,為每月)。
如果指定單個值的集合,則也可以計算該集合中值的總和。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Sum({file.QTY})

計算 QTY 字段中所有值的總和。

Sum({訂單.金額}, {訂單.客戶 ID})

對「金額」字段中每個訂單組的訂單求和(總計)。每當「客戶 ID」字段中的值變化時,訂單都將進行分組。

Sum({訂單.金額}, {訂單.日期}, "monthly") % Sum({訂單.金額 })

對「金額」字段中的值按月分組,並計算每個月組中值的總和相對於整個報表值的總和的百分比。

Sum([{file.AMOUNT}, {file.PRICE}, {file.COST}])

「金額」、「價格」和「費用」字段中值的總和。

注意: 在公式中使用此函數強制在打印時對公式求值。有關求值時間考慮因素的詳細信息,參見求值時間。



Average
Basic 語法和 Crystal 語法。

重載
Average (fld)
Average (fld, condFld)
Average (fld, condFld, cond)
Average (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠對報表中出現的值求平均值。例如:

如果銷售報表包含顯示每個訂單金額的字段,則可以計算該報表上出現的所有訂單的平均值(總計平均值)。
如果將訂單進行分組(例如,對訂單按其來自的省份進行分組),則可以計算每組訂單的平均金額(在本例中,為每個省)
如果將訂單按日期或布爾值分組(例如,按訂單發出的月份分組),則可以根據日期字段或布爾字段中的特定變化來計算每組訂單的平均金額(在本例中,為每月)。
如果指定單個值的數組,則也可以計算該集合的平均值。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Average({訂單.訂單金額})

計算「金額」字段中所有值的平均值。

Average ({訂單.訂單金額}, {客戶.客戶 ID})

得到向每個客戶銷售的平均金額。

下列示例適用於 Crystal 語法:

Average ([10,12,32,48])

計算一個常量數組中值的平均值。

注意: 在公式中使用此函數強制在打印時對公式求值。有關求值時間考慮因素的詳細信息,參見求值時間。

StdDev
Basic 語法和 Crystal 語法。

重載
StdDev (fld)
StdDev (fld, condFld)
StdDev (fld, condFld, cond)
StdDev (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠得到報表中一組值的標準偏差。例如:

您可以計算某個字段中所有值的總計標準偏差。
您可以計算某個組內所有值的標準偏差(例如,對銷售按來自的省進行分組)。
您可以計算其分組是由日期或布爾字段中的更改進行控制的組內所有值的標準偏差(例如,對銷售按其發生的月份分組)。
如果指定單個值的集合,則可以計算該集合中值的標準偏差。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

StdDev({file.RESULTS})

計算「結果」字段中所有值的標準偏差。

StdDev({訂單.金額}, {訂單.客戶 ID})

計算「訂單」字段每組訂單中訂單的標準偏差。每當「客戶」字段的值變化時,訂單都將進行分組。

StdDev({file.RESULTS}, {file.DATE}, "daily")

計算「結果」字段中每組試驗測試結果的偏差。每當「日期」字段中的值更改為新的日期時,測試結果都將進行分組。

StdDev({file.SCORES}, {file.NATURALIZED}, "any change")

根據測試者是否屬於某一國籍,對「分數」字段中的值進行分組,並計算每組分數的標準偏差。

下列示例適用於 Crystal 語法:

StdDev([({file.QTY1} * {file.PRICE1}),({file.QTY2} * {file.PRICE2}),({file.QTY3} * {file.PRICE3}), ({file.QTY4} * {file.PRICE4})])

返回 36.60,其中 Qty1 = 2,Price1 = 10.00,Qty2 = 2,Price2 = 2.00,Qty3 = 10,Price3 = 3.00 及 Qty4 = 8,Price4 = 11.00。

註釋
標準偏差是使用如下方法計算出來的:

計算樣本中項目的平均值。
從每個項目的值中減去平均值。
求每個項目差值的平方。
將樣本中所有項目的差值平方相加。
將總和除以示例中項目數減 1 (N - 1)。結果為方差。將此步與 PopulationStdDev 進行比較。
計算方差的平方根以得到標準偏差。
注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。



PopulationStdDev
Basic 語法和 Crystal 語法。

重載
PopulationStdDev (fld)
PopulationStdDev (fld, condFld)
PopulationStdDev (fld, condFld, cond)
PopulationStdDev (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。
有關此參數有效字符串的詳細信息,參見匯總函數的條件。

x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠得到報表中一組值的總體標準偏差。例如:

您可以計算某個字段中所有值的總計總體標準偏差。
您可以計算某個組內所有值的總體標準偏差(例如,對銷售按其來自的省進行分組)。
您可以計算其分組是由日期字段或布爾字段的變化所控制(例如,對銷售按其完成的月份進行分組)的組中所有值的總體標準偏差。
如果指定單個值的集合,則可以計算該集合值的總體標準偏差。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

PopulationStdDev({file.SCORES})

計算整個報表內「分數」字段中所有值的總體標準偏差。

PopulationStdDev({訂單.金額}, {訂單.客戶 ID})

計算「金額」字段每組訂單中訂單的總體標準偏差。每當「客戶 ID」字段中的值變化時,訂單都將進行分組。

PopulationStdDev({file.RESULTS}, {file.DATE}, "daily")

計算「結果」字段中每組試驗測試結果的偏差。每當「日期」字段中的值更改為新的日期時,測試結果都將進行分組。

下列示例適用於 Crystal 語法:

PopulationStdDev([{file.QTY1}, {file.QTY2}, {file.QTY3}, {file.QTY4}])

返回 3.57,其中 Qty1 = 2,Qty2 = 2,Qty3 = 10 和 Qty4 = 8。

註釋
總體標準偏差是使用如下方法計算出來的:

計算總體中項目的平均值。
從每個項目的值中減去平均值。
求每個項目差值的平方。
將總體中所有項目的差值平方相加。
將總和除以總體中的項目數 (N)。結果是總體方差。將此步與 StdDev 進行比較。
計算總體方差的平方根以得到總體標準偏差。
注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。





Variance
Basic 語法和 Crystal 語法。

重載
Variance (fld)
Variance (fld, condFld)
Variance (fld, condFld, cond)
Variance (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠得到報表中一組值的方差。例如:

您可以計算某個字段中所有值的總方差。
您可以計算某個組內所有值的方差(例如,對銷售按其來自的省進行分組)。
您可以計算其分組是由日期或布爾字段的變化所控制的組中所有值的方差(例如,對銷售按其完成的月份進行分組)。
如果指定單個值的集合,則可以計算該集合中值的方差。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Variance({file.AMOUNT})

計算「金額」字段中所有值的方差。

Variance({file.RESULTS}, {file.DATE},"daily")

計算「結果」字段中每組試驗測試結果的偏差。每當「日期」字段中的值更改為新的日期時,測試結果都將進行分組。

下列示例適用於 Crystal 語法:

Variance({file.SCORES}, {file.TEACHERS}) % Variance({file.SCORES})

對「分數」字段的值按教師進行分組,並計算每個教師組的方差與整個報表中的值(對於所有列出的教師)的方差的百分比。

Variance([{file.QTY1}, {file.QTY2}, {file.QTY3}, {file.QTY4}])

返回 17.00,其中 Qty1 = 2,Qty2 = 2,Qty3 = 10 和 Qty4 = 8。

註釋
方差是使用如下方法計算出來的:

計算樣本中項目的平均值。
從每個項目的值中減去平均值。
求每個項目差值的平方。
將樣本中所有項目的差值平方相加。
將總和除以示例中項目數減 1 (N - 1)。結果為方差。將最後一步與 PopulationVariance 進行比較。
注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。



PopulationVariance
Basic 語法和 Crystal 語法。

重載
PopulationVariance (fld)
PopulationVariance (fld, condFld)
PopulationVariance (fld, condFld, cond)
PopulationVariance (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的數字或貨幣值的數組。
返回
數字

操作
使您能夠得到報表中一組值的總體方差。例如:

您可以計算某個字段中所有值的總計總體方差。
您可以計算某個組內所有值的總體方差(例如,對銷售按其來自的省進行分組)。
您可以計算其分組是由日期或布爾字段中的變化所控制的組內所有值的總體方差(例如,對銷售按其完成的月份進行分組)。
如果指定單個值的集合,則可以計算該集合中值的總體方差。有關這種匯總的詳細信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

有關每種 PopulationVariance 函數的示例,請單擊相應的匯總函數。

PopulationVariance({file.CENSUS})

計算「統計」字段中所有值的方差。

PopulationVariance({file.RESULTS}, {file.PROCEDURE})

計算「結果」字段中每組試驗測試結果的總體方差。每當「過程」字段中的值更改時,測試結果都要分組。

PopulationVariance({file.SCORES}, {file.NATURALIZED}, "any change")

根據測試者是否屬於某一國籍,對「分數」字段中的值進行分組,並計算每組分數的總體方差。

下列示例適用於 Crystal 語法:

PopulationVariance({file.SCORES}, {file.TEACHERS}) % PopulationVariance({file.SCORES})

對「分數」字段中的值按教師進行分組,並計算每個教師組的總體方差佔整個報表中的值(對於列出的所有教師)的總體方差的百分比。

PopulationVariance([2,4,6,8,10])

返回 8。

註釋
總體方差是使用如下方法計算出來的:

計算總體中項目的平均值。
從每個項目的值中減去平均值。
求每個項目差值的平方。
將總體中所有項目的差值平方相加。
將總和除以總體中的項目數 (N)。結果是總體方差。將最後一步與 Variance 進行比較。
注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

Maximum
Basic 語法和 Crystal 語法。

重載
Maximum (fld)
Maximum (fld, condFld)
Maximum (fld, condFld, cond)
Maximum (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的值的數組或範圍。
返回
數字

操作
使您能夠得到一組值中的最大值。例如:

如果銷售報表包括一個顯示每個訂單金額的字段,則可以得到在報表上出現的所有訂單中金額最大的訂單(總計最大金額)。
如果將訂單進行分組(例如,對訂單按其來自的省進行分組),則可以得到每組中金額最大的訂單(在本例中,為每省)。
如果將訂單按日期或布爾值分組(例如,按訂單發出的月份進行分組),則可以根據日期或布爾字段中的特定變化來求得每組(在本例中,為每月)訂單中金額最大的訂單。
如果指定單個值的集合,則可以得到該集合的最大值。有關得到這種最大值的信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Maximum({訂單.訂單金額})

返回「金額」字段的最大值。

Maximum({訂單.金額}, {訂單.客戶R ID})

標識「金額」字段內每組訂單中最大的訂單(每個客戶的最大訂單)。每當「客戶 ID」字段中的值變化時,訂單都將進行分組。

Maximum({訂單.金額}, {訂單.訂單日期}, "monthly")

標識「金額」字段內每組訂單中最大的訂單(每個月的最大訂單)。每當「日期」字段中的值更改為新的月份時,訂單都將進行分組。

下列示例適用於 Crystal 語法:

Maximum 還允許設置計算中的下限值。例如,Maximum([{file.BALANCE}, 500]) 將 500 設置為計算的下限值。該表達式將始終返回餘額,除非餘額小於 500,此時,它將返回最低金額 500。因此:

Maximum([{file.PROFITS}, 500]) = {file.PROFITS}

其中 Profits > 500。

注意:

在公式中使用此函數強制在打印時對公式求值。有關求值時間考慮因素的詳細信息,參見求值時間。
使用此函數時,可以在函數獲得「最大值」之前使用 HasUpperBound (x) 函數測試範圍是否有「最大值」。
Minimum
Basic 語法和 Crystal 語法。

重載
Minimum (fld)
Minimum (fld, condFld)
Minimum (fld, condFld, cond)
Minimum (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的值的數組或範圍。
返回
小數數字

操作
使您能夠得出在一組值中出現的最小值。例如:

如果銷售報表包括一個顯示每個訂單金額的字段,則可以得到在報表上出現的所有訂單中金額最小的訂單(總計最小金額)。
如果對訂單進行分組(例如,對訂單按其來自的省進行分組),則可以得出每組中金額最小的訂單(在本例中,為每省)。
如果將訂單按日期或布爾值分組(例如,對訂單按其發出的月份進行分組),則可以根據日期或布爾字段中的特定變化來得出每組中金額最小的訂單(在本例中,為每月)。
如果指定單個值的集合,則可以得到該集合中的最小值。有關得出這種最小值的信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Minimum({file.QTY})

返回 QTY 字段的最小值。

Minimum({訂單.金額}, {訂單.客戶 ID})

標識「金額」字段內每組訂單中最小的訂單(每個客戶的最小訂單)。每當「客戶 ID」字段中的值變化時,訂單都將進行分組。

Minimum({訂單.金額}, {訂單.訂單日期}, "monthly")

標識「金額」字段內每組訂單中最小的訂單(每個月的最小訂單)。每當「日期」字段中的值更改為新的月份時,訂單都將進行分組。

下列示例適用於 Crystal 語法:

Minimum 還允許您設置計算時的上限值。例如:Minimum([{file.COMMISSION}, 2500]) 返回向最大值或上限 2500 美元增長的佣金。一旦增長的佣金超過 2500 美元的標記,此表達式即返回 2500。因此:

Minimum([{file.COMMISSION}, 2500])

返回 1575,其中 commission = 1575。

注意:

在公式中使用此函數強制在打印時對公式求值。有關求值時間考慮因素的詳細信息,參見求值時間。
使用此函數時,可以在函數獲取「最小值」之前使用 HasLowerBound (x) 函數測試範圍是否有「最小值」。


Count
Basic 語法和 Crystal 語法。

重載
Count (fld)
Count (fld, condFld)
Count (fld, condFld, cond)
Count (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的值的數組。
返回
數字

操作
使您能夠對報表中出現的值進行計數(對於指定字段)。例如:

如果銷售報表包含訂購的所有訂單及每個訂單的金額,則可以計算該報表上出現的訂單的總數(總計計數)。
如果對訂單進行分組(例如,對訂單按其來自的省進行分組),則可以計算每組(在本例中,為每個省)中的訂單數。
如果對訂單按日期或布爾值分組(例如,對訂單按其發出的月份進行分組),則可以根據日期或布爾字段中的特定變化來計算每組(在本例中,為每月)中的訂單數。
如果指定單個值的集合,則可以計算該集合中的值的數目。有關這種計數的信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Count({訂單.金額}, {訂單.客戶 ID})

此公式對「金額」字段內每組訂單中訂單的數目進行計數(每個客戶的訂單總計)。每當「客戶 ID」字段中的值變化時,訂單都將進行分組。

Count({訂單.訂單金額}, {訂單.訂單日期}, "monthly")

對「金額」字段內每組訂單中訂單的數目進行計數(每月訂單總計)。每當「日期」字段中的值更改為新的月份時,訂單都將進行分組。

下列示例適用於 Crystal 語法:

If Count({訂單.訂單 ID}) >= 100 Then

"Congratulations on meeting your quota!"

Else

""

如果訂單數大於或等於 100,則打印祝賀信息,如果訂單數小於 100,則什麼也不打印。

Count([1,2,3,4,5])

返回 5。對數組中值的總數進行計數。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

DistinctCount
Basic 語法和 Crystal 語法。

重載
DistinctCount (fld)
DistinctCount (fld, condFld)
DistinctCount (fld, condFld, cond)
DistinctCount (x)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
x 是可由正在使用的函數求值的值的數組。
返回
數字

操作
使您能夠得到報表中出現的值的非重複計數。例如:

如果銷售報表包含客戶訂購的所有訂單,則可以計算報表中出現的非重複客戶的總數(總計非重複計數),不包括任何重複記錄。如果客戶訂購一個以上的訂單,則忽略該重複的出現客戶。
如果對訂單進行分組(例如,對訂單按其來自的省進行分組),則可以計算每組(在本例中,為每省)中非重複客戶的數目。任何定購一張以上訂單的客戶以及在組中出現多次的客戶都只計數一次。
如果對訂單按日期或布爾值分組(例如,對訂單按其發出的月份進行分組),則可以根據日期或布爾字段中的特定變化來計算每組(在本例中,為每月)中非重複客戶的數目。如果客戶在一個月內發出一個以上的訂單,則該客戶的重複實例被忽略。
如果指定單個值的集合,則可以計算該集合中非重複值的數目。該集合中重複值只計數一次。有關這種非重複計數的信息,參見數組匯總函數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

DistinctCount({客戶.地區})

對「地區」字段中出現的不同省份進行計數,忽略任何重複省份。

DistinctCount({客戶.城市}, {客戶.地區})

計算每個「省」組中不同城市的數目。

DistinctCount({訂單.客戶 ID}, {訂單.訂單日期}, "weekly")

對所聯繫的不同客戶的數目進行計數,不包括後續聯繫人。每當「日期」字段中的值更改為新的星期時,客戶都將進行分組。

下列示例適用於 Crystal 語法:

DistinctCount([1,3,5,3,2,5])

返回 4。對數組中非重複值的數目進行計數。重複值被忽略。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

註釋
DistinctCount 對字段中非重複值的數目進行計數。重複值被忽略。

Correlation
Basic 語法和 Crystal 語法。

重載
Correlation (fld, fld)
Correlation (fld, fld, condFld)
Correlation (fld, fld, condFld, cond)
參數
fld 是任何數值字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
使您能夠計算指定字段的相關係數(即這些字段按相同方式變化的程度)。例如:

您可以計算報表中所有記錄的兩個字段的相關係數。
您可以對某個組(例如,對銷售按其來自的省進行分組)的所有值計算兩個字段的相關係數。
您可以對其分組由日期字段或布爾字段的變化進行控制的組(例如,對銷售按其完成的月份進行分組)的所有值計算兩個字段的相關係數。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Correlation({客戶.客戶 ID}, {客戶.信用 ID})

計算「客戶 ID」和「貸方 ID」字段之間的相關係數。

Correlation({訂單.客戶 ID}, {訂單.信用 ID}, {客戶.地區})

計算每個地區的「客戶 ID」和「貸方 ID」字段之間的相關係數。

Correlation({訂單.客戶 ID}, {訂單.信用 ID}, {客戶.地區}, "monthly")

計算每月每個「地區」組中所有值的「客戶 ID」和「貸方 ID」之間的相關係數。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

註釋
除非相關係數未定義,此時該函數被賦以空值 (0),否則相關係數始終是介於 -1 和 1 之間的一個數。如果相關係數為 0,則這些字段不相關。

Covariance
Basic 語法和 Crystal 語法。

重載
Covariance (fld, fld)
Covariance (fld, fld, condFld)
Covariance (fld, fld, condFld, cond)
參數
fld 是可由函數求值的任何數值字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
Covariance (協方差)是成對變量間的線性關係的度量(即兩個字段一起變化的趨勢)。當字段按照特定的數學關係變化時,則它們是協變的。圓的周長和圓的半徑是協變的。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

Covariance({table.FIELD1}, {table.FIELD2})

計算兩個字段的協方差,並以小數形式返回協方差。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

註釋
Covariance 是使用如下方法計算出來的:

計算每個樣本中項目的平均值(均值)。
從兩個樣本每個項目的值中減去平均值。
將每對項目的差值相乘。
計算該乘法中所有乘積的平均值。結果為協方差。


WeightedAverage
Basic 語法和 Crystal 語法。

重載
WeightedAverage (fld, fld)
WeightedAverage (fld, fld, condFld)
WeightedAverage (fld, fld, condFld, cond)
參數
fld 是可由函數求值的任何有效的數字數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
使您能夠計算指定字段的加權平均值。在計算加權平均值時,實際上是計算一個字段的平均值,然後使用另一個字段的值來對第一個字段中的每個值在平均值中的作用進行「加權」。在一般的平均值中,所有權數都等於 1。

例如:

您可以計算兩個字段的加權平均值。
您可以對某個組(例如,對銷售按其來自的省進行分組)的所有值計算兩個字段的加權平均值。
您可以對其分組由日期或布爾字段中的變化進行控制的組(例如,對銷售按其完成的月份進行分組)中的所有值計算兩個字段的加權平均值。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

WeightedAverage({table.FIELD1}, {table.FIELD2})

返回 3.5,其中兩個字段中每個字段都有四個值。Field1 具有值 3、2、5 和 1。Field2 具有值 0、1、1 和 0。WeightedAverage 計算如下:(3*0 + 2*1 + 5*1 + 1*0)/sum{table.FIELD2}) = 3.5。

注意: 在公式中使用此函數強制在打印時對公式求值。有關求值時間考慮因素的詳細信息,參見求值時間。

Median
Basic 語法和 Crystal 語法。

重載
Median (fld)
Median (fld, condFld)
Median (fld, condFld, cond)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
計算給定數值字段的中值。中值是指一個數值序列中的中間值(或者是一個偶數序列值中兩個中間值的平均值)。

例如:

您可以計算某個字段中所有值的中值。
您可以計算某個組(例如,對銷售按其來自的省進行分組)的一個字段中所有值的中值。
您可以計算其分組由日期或布爾字段中的變化進行控制的組(例如,對銷售按其完成的月份進行分組)內所有值的中值。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Median({客戶.去年銷售額})

返回 $29087,其中「去年銷售額」字段的值為 $27014、$28000、$29087、$34500 和 $48260。

Median({客戶.去年銷售額}, {客戶.地區)

對「去年銷售額」字段按地區進行分組,並返回每個地區「去年銷售額」字段的中值。

Median({訂單.訂單金額}, {客戶.地區}, "monthly")

對「金額」字段中的值按地區進行分組,然後返回每月中每個地區訂單金額的中值。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

PthPercentile
Basic 語法和 Crystal 語法。

重載
PthPercentile (P, fld)
PthPercentile (P, fld, condFld)
PthPercentile (P, fld, condFld, cond)
參數
P 是介於 0 和 100 之間的任何整數。
fld 是可由函數求值的任何數字字段或貨幣字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。
有關此參數有效字符串的詳細信息,參見匯總函數的條件。

返回
數字或貨幣值

操作
計算數字字段或貨幣字段中指定百分位 (P) 的值。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

PthPercentile(20, {客戶.去年銷售額})

返回 $2302 作為第 20 個百分位的值(如果 {客戶.去年銷售額} 的 20% 小於 $2302)。

PthPercentile(P, {客戶.去年銷售額}, {客戶.地區})

對「去年銷售額」字段按地區進行分組,並返回每個地區「去年銷售額」字段中百分位 P 值。

PthPercentile(P,{訂單.訂單金額}, {客戶.地區}, "monthly")

對「金額」字段中的值按地區進行分組,然後返回每月每個地區的「金額」字段的百分位 P 值。

註釋
當 P = 50(第 50 個百分位)時返回的值與 Median 函數(中值)返回的值相同。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

NthLargest
Basic 語法和 Crystal 語法。

重載
NthLargest (N, fld)
NthLargest (N, fld, condFld)
NthLargest (N, fld, condFld, cond)
參數
N 是從 1 到 100 之間(包括 1 和 100)的任何整數。
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
確定整個報表或每個 (condFld) 組實例中給定字段的第 N 個最大值。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

NthLargest(1, {客戶.客戶 ID}

返回 50,其中「客戶 ID」字段包含範圍從 12 到 50 的數值。

NthLargest(5, {客戶.客戶姓名}, {客戶.地區})

返回每個地區中」客戶名稱」字段的第 5 個最大值。

NthLargest(1, {訂單.訂單金額}, {客戶.地區}, "monthly")

對「金額」字段的值按地區進行分組,然後返回「金額」字段中每月每個地區的最大值。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

NthSmallest
Basic 語法和 Crystal 語法。

重載
NthSmallest (N, fld)
NthSmallest (N, fld, condFld)
NthSmallest (N, fld, condFld, cond)
參數
N 是從 1 到 100 之間(包括 1 和 100)的任何整數。
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
確定整個報表或每個 (condFld) 組實例中給定字段的第 N 個最小值。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

NthSmallest (1, {客戶.客戶 ID}

返回 12,其中「客戶 ID」字段包含範圍從 12 到 50 的數值。

NthSmallest(1, {客戶.客戶姓名}, {客戶.地區})

返回每個地區」客戶名稱」字段的最小值。

NthSmallest({訂單.訂單金額}, {客戶.地區}, "monthly")

對「金額」字段中的值按地區進行分組,然後返回「金額」字段中每個地區、每月的最小值。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

Mode
Basic 語法和 Crystal 語法。

重載
Mode (fld)
Mode (fld, condFld)
Mode (fld, condFld, cond)
參數
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
小數數字

操作
標識最常出現的值。

例如:

您可以計算某個字段中所有值的模。
您可以計算某個組(例如,對銷售按其來自的省進行分組)一個字段中所有值的模。
您可以計算其分組是由日期或布爾字段中的變化進行控制的組(例如,對銷售按其完成的月份進行分組)內所有值的模。
示例
下列示例適用於 Basic 語法和 Crystal 語法:

Mode({客戶.客戶姓名})

返回」客戶名稱」字段的模(最常出現的值)。

Mode({客戶.客戶姓名}, {客戶.地區})

對」客戶名稱」字段的值按地區進行分組,然後返回「客戶名稱」字段中每個地區的模。

Mode({客戶.客戶姓名}, {客戶.地區}, "monthly")

對「客戶名稱」字段中的值按地區進行分組,然後返回「客戶名稱」字段中每個地區、每月的模。

註釋
Mode 與 N = 1 時的 NthMost Frequent 用法相同。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

NthMostFrequent
Basic 語法和 Crystal 語法。

重載
NthMostFrequent (N, fld)
NthMostFrequent (N, fld, condFld)
NthMostFrequent (N, fld, condFld, cond)
返回
小數數字

參數
N 是從 1 到 100 之間(包括 1 和 100)的任何整數。
fld 是可由函數求值的任何有效的數據庫字段或公式字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
操作
確定整個報表或每個 (condFld) 組實例的給定字段中的第 N 個出現次數最多的值。如果該字段中沒有出現一次以上的值,則該函數將默認返回最小值。

典型用法
您可以使用此函數把注意力集中於特定字段中特別大或特別小的值。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

NthMostFrequent(1, {客戶.去年銷售額})

返回 $29087,其中值 $29087 在「去年銷售額」字段中出現的次數最多。

NthMostFrequent(2, {客戶.去年銷售額})

返回 $34700,其中 $34700 是「去年銷售額」字段中出現次數第二多的值。

NthMostFrequent(1, {客戶.去年銷售額}, {客戶.地區})

為 客戶.地區 組的一個實例返回 $48000,其中 $48000 是該組中出現次數最多的值;為該組的另一個實例返回 $34000,其中 $34000 是該組中出現次數最多的值;為該組的第三個實例返回 $9000,其中該組沒有出現任何重複值,$9000 是最小值。

註釋
當一個以上的值出現的次數相同時,最小值被認為是出現次數最多的值。例如,如果

NthMostFrequent(1, {客戶.去年銷售額})

返回值 ¥29087,而一個大於 ¥29087的值(例如,$35000)出現的次數與其相同,則 N = 1 的 NthMostFrequent 仍將返回 ¥29087,因為 ¥29087 較小。

注意: 在公式中使用此函數強制在打印時對公式求值。

有關求值時間考慮因素的詳細信息,參見求值時間。

PercentOfSum
Basic 語法和 Crystal 語法。

重載
PercentOfSum (fld, condFld)
PercentOfSum (fld, condFld, cond)
PercentOfSum (fld, innerCondFld, outerCondFld)
PercentOfSum (fld, innerCondFld, innerCond, outerCondFld)
PercentOfSum (fld, innerCondFld, outerCondFld, outerCond)
PercentOfSum (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字字段或貨幣字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。
有關此參數有效字符串的詳細信息,參見匯總函數的條件。

innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。
有關此參數有效字符串的詳細信息,參見匯總函數的條件。

返回
數字值

操作
PercentOfSum (fld, condFld) 與 100 * Sum (fld, condFld) / Sum (fld) 的結果相同。它將由 condFld 確定的組的字段 fld 的值的總和表示為總計和的百分比。

PercentOfSum (fld, condFld, cond) 與 100 * Sum (fld, condFld, cond) / Sum (fld) 的結果相同。字符串參數 cond 表達了一些其他信息,用來精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfSum (fld, innerCondFld, outerCondFld) 與 100 * Sum (fld, innerCondFld) / Sum (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組的 fld 字段的值的總和表示為由 outerCondFld 確定的組的總和的百分比。

PercentOfSum (fld, innerCondFld, innerCond, outerCondFld) 與 100 * Sum (fld, innerCondFld, innerCond) / Sum (fld, outerCondFld) 的結果相同。

PercentOfSum (fld, innerCondFld, outerCondFld, outerCond) 與 100 * Sum (fld, innerCondFld) / Sum (fld, outerCondFld, outerCond) 的結果相同。

PercentOfSum (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * Sum (fld, innerCondFld, innerCond) / Sum (fld, outerCondFld, outerCond) 的結果相同。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

PercentOfSum ({訂單.訂單金額}, {訂單.訂單日期}, "annually")

返回給定年中定購的訂單的總值占所有訂單的總值的百分數。

PercentOfSum ({訂單.訂單金額}, {訂單.承運商})

返回通過給定運輸公司運輸的訂單的總值,用占所有訂單的總值的百分比表示。

PercentOfSum ({產品.價格 (SRP)}, {產品.規格}, {產品.產品類別})

返回給定大小和類別的產品的總價格,用占相同給定類別的產品的總價格的百分比表示。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。

PercentOfAverage
Basic 語法和 Crystal 語法。

重載
PercentOfAverage (fld, condFld)
PercentOfAverage (fld, condFld, cond)
PercentOfAverage (fld, innerCondFld, outerCondFld)
PercentOfAverage (fld, innerCondFld, innerCond, outerCondFld)
PercentOfAverage (fld, innerCondFld, outerCondFld, outerCond)
PercentOfAverage (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字字段或貨幣字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。
innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。
有關這些參數的有效字符串的信息,參見匯總函數的條件。

返回
數字值。

操作
PercentOfAverage (fld, condFld) 與 100 * Average (fld, condFld) / Average (fld) 的結果相同。它將由 condFld 確定的組的 fld 字段的平均值表示為 fld 的所有值的平均值的百分比。

PercentOfAverage (fld, condFld, cond) 與 100 * Average (fld, condFld, cond) / Average (fld) 的結果相同。字符串參數 cond 表達了一些其他信息,用來精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfAverage (fld, innerCondFld, outerCondFld) 與 100 * Average (fld, innerCondFld) / Average (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組的字段 fld 的值表示為由 outerCondFld 確定的組的平均值的百分比。

PercentOfAverage (fld, innerCondFld, innerCond, outerCondFld) 與 100 * Average (fld, innerCondFld, innerCond) / Average (fld, outerCondFld) 的結果相同。

PercentOfAverage (fld, innerCondFld, outerCondFld, outerCond) 與 100 * Average (fld, innerCondFld) / Average (fld, outerCondFld, outerCond) 的結果相同。

PercentOfAverage (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * Average (fld, innerCondFld, innerCond) / Average (fld, outerCondFld, outerCond) 的結果相同。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。

PercentOfMaximum
Basic 語法和 Crystal 語法

重載
PercentOfMaximum (fld, condFld)
PercentOfMaximum (fld, condFld, cond)
PercentOfMaximum (fld, innerCondFld, outerCondFld)
PercentOfMaximum (fld, innerCondFld, innerCond, outerCondFld)
PercentOfMaximum (fld, innerCondFld, outerCondFld, outerCond)
PercentOfMaximum (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字字段或貨幣字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
數字值。

操作
PercentOfMaximum (fld, condFld) 與 100 * Maximum (fld, condFld) / Maximum (fld) 的結果相同。它將由 condFld 確定的組的字段 fld 的值的最大值表示為 fld 的所有值的最大值的百分比。

PercentOfMaximum (fld, condFld, cond) 與 100 * Maximum (fld, condFld, cond) / Maximum (fld) 的結果相同。字符串參數 cond 表達了一些其他信息,用來精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfMaximum (fld, innerCondFld, outerCondFld) 與 100 * Maximum (fld, innerCondFld) / Maximum (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組的字段 fld 的值的最大值表示為由 outerCondFld 確定的組的最大值的百分比。

PercentOfMaximum (fld, innerCondFld, innerCond, outerCondFld) 與 100 * Maximum (fld, innerCondFld, innerCond) / Maximum (fld, outerCondFld) 的結果相同

PercentOfMaximum (fld, innerCondFld, outerCondFld, outerCond) 與 100 * Maximum (fld, innerCondFld) / Maximum (fld, outerCondFld, outerCond) 的結果相同。

PercentOfMaximum (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * Maximum (fld, innerCondFld, innerCond) / Maximum (fld, outerCondFld, outerCond) 的結果相同。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。

PercentOfMinimum
Basic 語法和 Crystal 語法。

重載
PercentOfMinimum (fld, condFld)
PercentOfMinimum (fld, condFld, cond)
PercentOfMinimum (fld, innerCondFld, outerCondFld)
PercentOfMinimum (fld, innerCondFld, innerCond, outerCondFld)
PercentOfMinimum (fld, innerCondFld, outerCondFld, outerCond)
PercentOfMinimum (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字字段或貨幣字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
數字值。

操作
PercentOfMinimum (fld, condFld) 與 100 * Minimum (fld, condFld) / Minimum (fld) 的結果相同。它將由 condFld 確定的組的字段 fld 的值的最小值表示為 fld 的所有值的最小值的百分比。

PercentOfMinimum (fld, condFld, cond) 與 100 * Minimum (fld, condFld, cond) / Minimum (fld) 的結果相同。字符串參數 cond 表達了一些其他信息,用來精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfMinimum (fld, innerCondFld, outerCondFld) 與 100 * Minimum (fld, innerCondFld) / Minimum (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組的字段 fld 的值的最小值表示為由 outerCondFld 確定的組的最小值的百分比。

PercentOfMinimum (fld, innerCondFld, innerCond, outerCondFld) 與 100 * Minimum (fld, innerCondFld, innerCond) / Minimum (fld, outerCondFld) 的結果相同。

PercentOfMinimum (fld, innerCondFld, outerCondFld, outerCond) 與 100 * Minimum (fld, innerCondFld) / Minimum (fld, outerCondFld, outerCond) 的結果相同。

PercentOfMinimum (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * Minimum (fld, innerCondFld, innerCond) / Minimum (fld, outerCondFld, outerCond) 的結果相同。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。

PercentOfCount
Basic 語法和 Crystal 語法。

重載
PercentOfCount (fld, condFld)
PercentOfCount (fld, condFld, cond)
PercentOfCount (fld, innerCondFld, outerCondFld)
PercentOfCount (fld, innerCondFld, innerCond, outerCondFld)
PercentOfCount (fld, innerCondFld, outerCondFld, outerCond)
PercentOfCount (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字、貨幣、字符串、日期、時間或日期時間字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
數字值。

操作
PercentOfCount (fld, condFld) 與 100 * Count (fld, condFld) / Count (fld) 的結果相同。它將由 condFld 確定的組的 fld 字段的值的計數表示為 fld 的所有值的計數的百分比。

PercentOfCount (fld, condFld, cond) 與 100 * Count (fld, condFld, cond) / Count (fld) 的結果相同。字符串參數 cond 表達了一些其他信息,用來精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfCount (fld, innerCondFld, outerCondFld) 與 100 * Count (fld, innerCondFld) / Count (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組的字段 fld 的值的計數表示為由 outerCondFld 確定的組的計數的百分比。

PercentOfCount (fld, innerCondFld, innerCond, outerCondFld) 與 100 * Count (fld, innerCondFld, innerCond) / Count (fld, outerCondFld) 的結果相同。

PercentOfCount (fld, innerCondFld, outerCondFld, outerCond) 與 100 * Count (fld, innerCondFld) / Count (fld, outerCondFld, outerCond) 的結果相同。

PercentOfCount (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * Count (fld, innerCondFld, innerCond) / Count (fld, outerCondFld, outerCond) 的結果相同。

示例
下列示例適用於 Basic 語法和 Crystal 語法:

PercentOfCount ({訂單.訂單 ID}, {訂單.訂單日期}, "annually")

返回在給定的年內定購的訂單總數,用占所有訂單總數的百分比表示。

PercentOfCount ({訂單.訂單 ID}, {訂單.承運商})

返回通過給定運輸公司運輸的訂單總數,用占所有訂單總數的百分比表示。

PercentOfCount ({產品.產品 ID}, {產品.規格}, {產品.產品類別})

返回給定大小和類別的產品總數,用占相同給定類別的產品總數的百分比表示。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。

PercentOfDistinctCount
Basic 語法和 Crystal 語法。

重載
PercentOfDistinctCount (fld, condFld)
PercentOfDistinctCount (fld, condFld, cond)
PercentOfDistinctCount (fld, innerCondFld, outerCondFld)
PercentOfDistinctCount (fld, innerCondFld, innerCond, outerCondFld)
PercentOfDistinctCount (fld, innerCondFld, outerCondFld, outerCond)
PercentOfDistinctCount (fld, innerCondFld, innerCond, outerCondFld, outerCond)
參數
fld 是可由函數求值的數字、貨幣、字符串、日期、時間或日期時間字段。
condFld 是用於對 fld 中的值進行分組時所依據的字段。
cond 是表明 condFld 分組類型的字符串。只能在 condFld 是一個日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
innerCondFld 是用於對 fld 中的值進行分組時所依據的字段。
innerCond 是表明 innerCondFld 分組類型的字符串。只能在 innerCondFld 是日期、時間、日期時間或布爾字段時才指定該參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
outerCondFld 是一個用作對 fld 中的值的分組依據的字段。
outerCond 是表明 outerCondFld 分組類型的字符串。只能在 outerCondFld 是日期、時間、日期時間或布爾字段時才指定此參數。有關此參數有效字符串的詳細信息,參見匯總函數的條件。
返回
數字值。

操作
PercentOfDistinctCount (fld, condFld) 與 100 * DistinctCount (fld, condFld) / DistinctCount (fld) 的結果相同。它將由 condFld 確定的組的字段 fld 的值的非重複計數表示為 fld 的所有值的非重複計數的百分比。

PercentOfDistinctCount (fld, condFld, cond) 與 100 * DistinctCount (fld, condFld, cond) / DistinctCount (fld) 的結果相同。字符串參數 cond 表達一些其他信息,用於精確地指定分組。例如,如果 condFld 是一個日期字段,則為分組「每天」、「每週」或「每月」等。

PercentOfDistinctCount (fld, innerCondFld, outerCondFld) 與 100 * DistinctCount (fld, innerCondFld) / DistinctCount (fld, outerCondFld) 的結果相同。它將由 innerCondFld 確定的組中 fld 字段的值的非重複計數表示為由 outerCondFld 確定的組的非重複計數的百分比。

PercentOfDistinctCount (fld, innerCondFld, innerCond, outerCondFld) 與 100 * DistinctCount (fld, innerCondFld, innerCond) / DistinctCount (fld, outerCondFld) 的結果相同。

PercentOfDistinctCount (fld, innerCondFld, outerCondFld, outerCond) 與 100 * DistinctCount (fld, innerCondFld) / DistinctCount (fld, outerCondFld, outerCond) 的結果相同。

PercentOfDistinctCount (fld, innerCondFld, innerCond, outerCondFld, outerCond) 與 100 * DistinctCount (fld, innerCondFld, innerCond) / DistinctCount (fld, outerCondFld, outerCond) 的結果相同。

註釋
此函數和其他百分比函數用於支持「百分比匯總」字段。作為參數提供的分組必須在報表中實際存在,以便匯總函數調用成功。