Featured

QTP 10 not Recognizing Oracle Forms Obje

Bidun Meduza shared on our Facebook page a problem and solution that I thought might be useful to you too. Problem He had a situation where QTP 10 was unable to recognize objects of Oracle Forms. Th

Read More
QTP 10 not Recognizing Oracle Forms Objects

New Navigation Menus

In order to ease orientation through our vast knowledge archive, we have added the following navigation menus: First Steps Scripting QTP VBScript Tutorial Knowledge Articles (by levels of expertise) B

Read More
New Navigation Menus

Permalinks

We’ve changed the permalinks format, so if you have been experiencing some trouble with finding materials with the old links, then remove the YYYY/MM/ from the URL and you’d be fine. In ca

Read More
Permalinks

Advanced QTP on Android

A first version of AdvancedQTP for Android can be found here. Now you can take this perfect companion with you to keep updated on what’s new in our site.

Read More
Advanced QTP on Android

New Advanced QTP Features: Layout and FB

As you have most surely noticed, we’ve recently changed the site’s theme in order to enhance the overall user experience. As from today, you can also register and login seamlessly with you

Read More
New Advanced QTP Features: Layout and FB Integration

Display records where “Departure_Initials” starts with an “L”

0
by on April 12, 2008 at 05:29

This example uses the QTP_Flight32 DSN to database connection.

The example is based on the Flight Reservation demo database.

[hideit]

<span style="color: #0000ff;">Dim</span> oConn, oRst, oField
<span style="color: #0000ff;">Dim</span> sql, nCount

nCount = 1
<span style="color: #0000ff;">set</span> oConn = CreateObject( <span style="color: #006080;">"ADODB.Connection"</span> )

oConn.Open <span style="color: #006080;">"QT_Flight32"</span>
<span style="color: #0000ff;">set</span> oRst = CreateObject( <span style="color: #006080;">"ADODB.recordset"</span> )
sql = <span style="color: #006080;">"SELECT Flight_Number, Airlines FROM Flights WHERE Departure_Initials LIKE \'L%\'"</span>
oRst.Open sql, oConn

<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> oField <span style="color: #0000ff;">in</span> oRst.Fields
    DataTable.LocalSheet.AddParameter oField.Name, vbNullString
<span style="color: #0000ff;">Next</span>

<span style="color: #0000ff;">Do</span> <span style="color: #0000ff;">Until</span> oRst.EOF
    <span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> oField <span style="color: #0000ff;">in</span> oRst.Fields
        DataTable( oField.Name, dtLocalSheet ) = oField.Value
    <span style="color: #0000ff;">Next</span>
    oRst.MoveNext
    DataTable.LocalSheet.SetCurrentRow nCount
    nCount = nCount + 1
    <span style="color: #0000ff;">If</span> nCount > 30 <span style="color: #0000ff;">Then</span>
        <span style="color: #0000ff;">Exit</span> <span style="color: #0000ff;">Do</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>
<span style="color: #0000ff;">Loop</span>
oRst.close
oConn.close

[/hideit]

, ,

Determine which Version of Access was Used to Create a Database

0
by on April 1, 2008 at 17:39

While looking up something else in the Access documentation we ran across a property named FileFormat. FileFormat is the property that tells us which version of Access was used to create a database. Want to know which version of Access was used to create the database flight32.mdb? ( The flight application’s QTP demo ) Here you go:

<span style="color: #0000ff;">Set</span> access = CreateObject( <span style="color: #006080;">"Access.Application"</span> )
flight32 = Environment( <span style="color: #006080;">"ProductDir"</span> ) & <span style="color: #006080;">"\samples\flight\app\flight32.mdb"</span>
access.OpenCurrentDatabase flight32

formatNum = access.CurrentProject.FileFormat

<span style="color: #0000ff;">Select</span> <span style="color: #0000ff;">Case</span> formatNum
    <span style="color: #0000ff;">Case</span> 2 Print <span style="color: #006080;">"Microsoft Access 2"</span>
    <span style="color: #0000ff;">Case</span> 7 Print <span style="color: #006080;">"Microsoft Access 95"</span>
    <span style="color: #0000ff;">Case</span> 8 Print <span style="color: #006080;">"Microsoft Access 97"</span>
    <span style="color: #0000ff;">Case</span> 9 Print <span style="color: #006080;">"Microsoft Access 2000"</span>
    <span style="color: #0000ff;">Case</span> 10 Print <span style="color: #006080;">"Microsoft Access 2003"</span>
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Select</span>

Note. By default, Access will present you with a dialog box asking if you really want to open the database. To bypass that warning, set your macro security level to Low.

We begin by creating an instance of the Access.Application object, then we use the OpenCurrentDatabase method to open the file flight32.mdb. We then use this line of code to get the value of the FileFormat property and store that value in a variable named formatNum:

formatNum = access.CurrentProject.FileFormat

All that’s left now is to set up a Select Case statement to examine the value of formatNum and print the corresponding version of Microsoft Access.

Based on “How Can I Determine Which Version of Access was Used to Create a Database? ” from the Scripting Guys

, ,

Create and Delete a DSN

0
by on April 1, 2008 at 05:46

a DSN, is a way for you to connect to a database merely by referencing the DSN name, and without having to specify the entire path to the database. That’s particularly handy if you have a bunch of scripts that access this database. If you hard-code the path into the scripts and then move the database from one server to another, you’ll have to edit the path on each and every script. If you use a DSN, however, you won’t have to edit the scripts at all; instead, you just need to modify the DSN. That’s one change versus hundreds of changes (depending on how many scripts you have).

You can create DSNs that use other ODBC databases (Access, Oracle, FoxPro, whatever). However, the registry keys and values used when creating a DSN to access an Oracle database aren’t necessarily the same as those used to access a SQL Server database. If you’re using SQL Server, you can just copy our script and change the names of the database, the server, etc. If you’re using a different database, we’d recommend that you manually create a DSN. After you do that, fire up your favorite registry editor and look for the DSN here:

HKLM\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources

And here:

HKLM\SOFTWARE\ODBC\ODBC.INI\YourDSN

Take a look at the registry keys and values required for that type of database, and then plug that information into our script. If you aren’t sure how to do that, give us a week or two, and we’ll see what we can do about getting some sample scripts for different ODBC databases posted in the Script Center. At any rate, here’s a script that creates a DSN that uses SQL Server:

<span style="color: #0000ff;">Const</span> HKLM = &H80000002

computer = <span style="color: #006080;">"."</span>
<span style="color: #0000ff;">Set</span> reg = GetObject( <span style="color: #006080;">"winmgmts:{impersonationLevel=impersonate}!\\"</span> & _
                     computer & <span style="color: #006080;">"\root\default:StdRegProv"</span> )

keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources"</span>
valueName = <span style="color: #006080;">"Script Repository"</span>
valueStr = <span style="color: #006080;">"SQL Server"</span>
reg.SetStringValue HKLM, keyPath, valueName, valueStr

keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBC.INI\Script Repository"</span>
reg.CreateKey HKLM, keyPath
valueName = <span style="color: #006080;">"Database"</span>
valueStr = <span style="color: #006080;">"Script Center"</span>
reg.SetStringValue HKLM, keyPath, valueName, valueStr

valueName = <span style="color: #006080;">"Driver"</span>
valueStr = <span style="color: #006080;">"C:\WINDOWS\System32\SQLSRV32.dll"</span>
reg.SetStringValue HKLM, keyPath, valueName, valueStr

valueName = <span style="color: #006080;">"Server"</span>
valueStr = <span style="color: #006080;">"srv-man-01"</span>
reg.SetStringValue HKLM, keyPath, valueName, valueStr

valueName = <span style="color: #006080;">"Trusted_Connection"</span>
valueStr = <span style="color: #006080;">"Yes"</span>
reg.SetStringValue HKLM, keyPath, valueName, valueStr

is long, but that’s because there are a number of registry keys and values that have to be created. For the most part, though, the script is pretty-straight forward. We start by setting the constant HKLM to &H80000002, the value required to connect to the HKLM portion of the registry. We then bind to the WMI service

From there we create a new registry value (HKLM\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources\Script Repository), with Script Repository the name we’re giving to our new DSN. We set the value of this, well, value to SQL Server, because that’s the type of database we’re connecting to.

After that we create a new registry key: HKLM\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources\Script Repository (note that the key name is the same as our DSN Name). We then need to configure the following registry values

clip_image001 Database — Name of the actual database we want to connect to. In this example, the database is named ScriptCenter.

clip_image001[1] Driver — Path to SQL Server ODBC drive. In this example, that path is C:\Windows\System32\SQLSRV32.dll.

clip_image001[2] Server — Name of the server where the database is found. In this case, the server name is srv-man-01.

clip_image001[3] Trusted_Connection — Tells SQL Server to use our logon credentials when accessing the database. This enables us to connect to the database without having to supply a user name and password.

Run the script, and you’ll have yourself a fully-functioning DSN.

And what about getting rid of that DSN once you’re finished with it? After all, we just need to delete the registry keys and values our first script created. Here’s a script that will delete the DSN Script Repository :

<span style="color: #0000ff;">Const</span> HKLM = &H80000002

computer = <span style="color: #006080;">"."</span>
<span style="color: #0000ff;">Set</span> reg = GetObject( <span style="color: #006080;">"winmgmts:{impersonationLevel=impersonate}!\\"</span> & _
                     computer & <span style="color: #006080;">"\root\default:StdRegProv"</span>)

keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBC.INI\Script Repository"</span>
reg.DeleteKey HKLM, keyPath

keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources"</span>
valueStr = <span style="color: #006080;">"Script Repository"</span>
reg.DeleteValue HKLM, keyPath, valueStr

Based on “Can I Create and Delete a DSN Using a Script?” from the Scripting Guys.

 

,

Get a list of the ODBC drivers installed

0
by on April 1, 2008 at 05:42

clip_image002

The registry, is the upstairs closet of the operating system: if you’re willing to look, you can find almost anything in the registry. That’s where can be found the list of installed ODBC drivers, in HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers.

<span style="color: #0000ff;">Const</span> HKLM = &H80000002

<span style="color: #0000ff;">Set</span> reg = GetObject( <span style="color: #006080;">"winmgmts:\\.\root\default:StdRegProv"</span> )
keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"</span>
reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr

<span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> UBound( valueNamesArr )
    reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr
    Print valueNamesArr( i ) & <span style="color: #006080;">" --> "</span> & valueStr
<span style="color: #0000ff;">Next</span>

We begin by defining a constant named HKLM and setting the value to &H80000002; we’ll use this constant to indicate that we want to work with the HKLM registry hive. We connect to the WMI service and to the standard registry provider (root\default:StdRegProv), then use this line of code to assign the registry path within HKLM to the variable keyPath

keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"</span>

As it turns out, the installed ODBC drivers are stored as individual registry values within this registry key, something like this:

clip_image002[4]

Therefore, to retrieve a collection of all these registry values we need to call the EnumValues method, a method which automatically grabs all the values within a specified key:

reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr

When we call EnumValues we need to supply two in parameters and two out parameters. “In parameters” are values we supply to the method; in this script we pass the constant HKLM and the variable keyPath. Taken together, these parameters tell the script which registry key we’re working with

“Out parameters” represent information that the method provides to us. To get this information all we have to do is provide a pair of variable names. In our script, the variable valueNamesArr will end up holding an array of all the registry value names found in SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers; the variable valueTypesArr will hold an array of data types for each of these registry values. this particular parameter included, only because it’s required.

After calling EnumValues all the individual registry value names will be stored (as an array) in the variable valueNamesArr. To access those values we need to set up a For-Next loop that runs from 0 to the last item (the upper bound or UBound) in the array. That’s what this line of code does:

<span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> UBound( valueNamesArr )

To actually get the values that have been assigned to those registry entries we need to call the GetStringValue method, something we do here:

reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr

As you can see, we pass GetStringValue four parameters:

clip_image001 HKLM, representing the registry hive.

clip_image001[1] keyPath, the registry path within HKLM.

clip_image001[2] valueName, representing the individual registry value.

clip_image001[3] valueStr, an out parameter which will store the value of the registry entry.

After that we can simply use this line of code to print back the name of the registry value and the value assigned to it:

Print valueNamesArr( i ) & <span style="color: #006080;">" --> "</span> & valueStr

clip_image002[6]

Based on “How Can I Get a List of the ODBC Drivers that are Installed on a Computer?” from the Scripting Guys.

, ,

Retrieve a list of the system DSNs installed

0
by on April 1, 2008 at 05:40

If you have no idea what we’re talking about System DSNs are simply a shortcut method for connecting to databases and other data sources. You can view a list of the System DSNs available on a computer by bringing up the ODBC Data Source Administrator dialog box and looking on the System DSN tab

clip_image002

That’s fine if you’re working on the local machine. But what if you’re interested in retrieving a list of the System DSNs on a remote machine, or what if you’d like to inventory the System DSNs on a whole bunch of computers? How do you do something like that?

<span style="color: #0000ff;">Const</span> HKLM = &H80000002

<span style="color: #0000ff;">Set</span> reg = GetObject( <span style="color: #006080;">"winmgmts:\\.\root\default:StdRegProv"</span> )
keyPath = <span style="color: #006080;">"SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES"</span>
reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr

<span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> UBound( valueNamesArr )
    reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr
    Print valueNamesArr( i ) & <span style="color: #006080;">" --> "</span> & valueStr
<span style="color: #0000ff;">Next</span>

For some reason, there’s no WMI class or other COM object designed to retrieve System DSNs. But that’s OK: because this information is stored in the registry we can still write a script to grab and return the DSNs. As you might expect, that’s exactly what the preceding script does: it opens the registry, zips down to HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES, and then returns the names and values of the all the registry entries found there. Each entry will consist of a name (representing the DSN name) and a value (representing the DSN driver). We’ll return and print both the name and the value, thus replicating the information found in the dialog box.

Our script begins by defining a constant named HKLM and setting the value to &H80000002; we’ll use this constant to indicate the registry hive we want to work with. We then bind to the WMI service, connecting to the StdRegProv class

Following that, we assign the registry path within HKLM to a variable named keyPath. With that done we can then use this line of code to call the EnumValues method and return a list of all the registry values stored in HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES:

reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr

As you can see, we pass EnumValues four parameters. The first two – HKLM and keyPath – are “in parameters” that represent the registry hive and registry path. The second two – valueNamesArr and valueTypesArr – are “out parameters;” that means they represent information that the EnumValues method returns to us. After EnumValues runs, valueNamesArr will be populated with the names of all the registry values found in HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES; valueTypesArr, meanwhile, will be populated with the registry data type for all those values.

At this point in time we have the name of each registry entry; if all we wanted to do was echo back the name we’d practically be done. However, we also wanted to echo back the value (that is, the driver name) for each DSN. To do that, we need to connect to each individual registry entry and return the value. And to do that we need to set up a For Next loop that walks through the array of registry entries. For each item in that array, we assign the DSN. We then call the GetStringValue method to return the value assigned to that registry entry:

reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr

In this script, strValue is an out parameter that contains the registry value. We now have the DSN name in one variable (strValueName) and the DSN driver in another variable (strValue). All that’s left is to display that information .

Print valueNamesArr( i ) & <span style="color: #006080;">" --> "</span> & valueStr

Based on “How Can I Retrieve a List of the System DSNs on a Computer?” from the Scripting Guys.

, , ,

Sort data with disconnected record set

0
by on April 1, 2008 at 05:39

Sorts numerical data using a disconnected record set.

[hideit]

<span style="color: #0000ff;">Const</span> adInteger = 3
<span style="color: #0000ff;">Const</span> MaxCharacters = 10
<span style="color: #0000ff;">Dim</span> sampleArr( 20 )

<span style="color: #0000ff;">For</span> i = LBound( sampleArr ) <span style="color: #0000ff;">to</span> UBound( sampleArr )
   sampleArr( i ) = RandomNumber( 1, 1000 )
<span style="color: #0000ff;">Next</span>
Print <span style="color: #006080;">"Array before sorting :"</span>
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> num <span style="color: #0000ff;">In</span> sampleArr
  Print num
<span style="color: #0000ff;">Next</span>
<span style="color: #008000;">\' ** creating disconnected record set object</span>
<span style="color: #0000ff;">Set</span> dataList = CreateObject( <span style="color: #006080;">"ADOR.Recordset"</span> )
dataList.Fields.Append <span style="color: #006080;">"Number"</span>, adInteger
dataList.Open
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> num <span style="color: #0000ff;">In</span> sampleArr
  dataList.AddNew
  dataList( <span style="color: #006080;">"Number"</span> ) = num
  dataList.Update
<span style="color: #0000ff;">Next</span>
dataList.Sort = <span style="color: #006080;">"Number"</span>
dataList.MoveFirst
Print <span style="color: #006080;">"Array after sorting :"</span>
<span style="color: #0000ff;">Do</span> <span style="color: #0000ff;">Until</span> dataList.EOF
  Print dataList.Fields.Item( <span style="color: #006080;">"Number"</span> )
  dataList.MoveNext
<span style="color: #0000ff;">Loop</span>
dataList.Close

[/hideit]

, ,

Add a New Record to a Table

0
by on April 1, 2008 at 05:37

The following code demonstrates how to add a new record to a table. The example uses the Flight Reservation Database.

<span style="color: #0000ff;">Const</span> adOpenStatic = 3
<span style="color: #0000ff;">Const</span> adLockOptimistic = 3

<span style="color: #0000ff;">Set</span> oConn = CreateObject( <span style="color: #006080;">"ADODB.Connection"</span> )
<span style="color: #0000ff;">Set</span> oRst = CreateObject( <span style="color: #006080;">"ADODB.Recordset"</span> )

oConn.Open <span style="color: #006080;">"QT_Flight32"</span>

oRst.Open <span style="color: #006080;">"SELECT * FROM Flights"</span> , oConn, adOpenStatic, adLockOptimistic

oRst.AddNew
oRst( <span style="color: #006080;">"Flight_Number"</span> ).Value = 21000
oRst( <span style="color: #006080;">"Departure_Initials"</span> ).Value = <span style="color: #006080;">"TLV"</span>
oRst( <span style="color: #006080;">"Departure"</span> ).Value = <span style="color: #006080;">"Tel Aviv"</span>
oRst( <span style="color: #006080;">"Day_Of_Week"</span> ).Value = <span style="color: #006080;">"Sunday"</span>
oRst( <span style="color: #006080;">"Arrival_Initials"</span> ).Value = <span style="color: #006080;">"BSA"</span>
oRst( <span style="color: #006080;">"Arrival"</span> ).Value = <span style="color: #006080;">"Buenos Aires"</span>
oRst( <span style="color: #006080;">"Departure_Time"</span> ).Value  = <span style="color: #006080;">"11:00 PM"</span>
oRst( <span style="color: #006080;">"Arrival_Time"</span> ).Value = <span style="color: #006080;">"11:00 AM"</span>
oRst( <span style="color: #006080;">"Airlines"</span> ).Value = <span style="color: #006080;">"EL-AL"</span>
oRst( <span style="color: #006080;">"Seats_Available"</span> ).Value = 220
oRst( <span style="color: #006080;">"Ticket_Price"</span> ).Value = 1400
oRst.Update
oRst.Close : oConn.Close
<span style="color: #0000ff;">Set</span> oRst = <span style="color: #0000ff;">Nothing</span> : <span style="color: #0000ff;">Set</span> oConn = <span style="color: #0000ff;">Nothing</span>

, ,

Create a New JET Database

0
by on April 1, 2008 at 05:35

The following code demonstrates how to create a new database named New_db.mdb.

<span style="color: #0000ff;">Set</span> oConn = CreateObject( <span style="color: #006080;">"ADOX.Catalog"</span> )

oConn.Create <span style="color: #006080;">"Provider = Microsoft.Jet.OLEDB.4.0; "</span> & _
        <span style="color: #006080;">"Data Source = new_db.mdb"</span>

, ,

Create a Table in a JET Database

0
by on April 1, 2008 at 05:33

The following code demonstrates how to create a new table in the Flight32.mdb

<span style="color: #0000ff;">Set</span> oConn = CreateObject( <span style="color: #006080;">"ADODB.Connection"</span> )

oConn.Open <span style="color: #006080;">"QT_Flight32"</span>

oConn.Execute <span style="color: #006080;">"CREATE TABLE EventTable("</span> & _
    <span style="color: #006080;">"EventKey COUNTER ,"</span> & _
    <span style="color: #006080;">"Category TEXT(50) ,"</span> & _
    <span style="color: #006080;">"ComputerName TEXT(50) ,"</span> & _
    <span style="color: #006080;">"EventCode INTEGER ,"</span> & _
    <span style="color: #006080;">"RecordNumber INTEGER ,"</span> & _
    <span style="color: #006080;">"SourceName TEXT(50) ,"</span> & _
    <span style="color: #006080;">"TimeWritten DATETIME ,"</span> & _
    <span style="color: #006080;">"UserName TEXT(50) ,"</span> & _
    <span style="color: #006080;">"EventType TEXT(50) ,"</span> & _
    <span style="color: #006080;">"Logfile TEXT(50) ,"</span> & _
    <span style="color: #006080;">"Message MEMO)"</span>

oConn.Close

clip_image002

, ,

Delete a Record from a Recordset

0
by on April 1, 2008 at 05:31

The following code demonstrates how to delete a record from a table. The example uses the Flight Reservation Database ( non default records )

 

<span style="color: #0000ff;">Const</span> adOpenStatic = 3
<span style="color: #0000ff;">Const</span> adLockOptimistic = 3
<span style="color: #0000ff;">Const</span> adUseClient = 3
<span style="color: #0000ff;">Set</span> oConn = CreateObject( <span style="color: #006080;">"ADODB.Connection"</span> )
<span style="color: #0000ff;">Set</span> oRst = CreateObject( <span style="color: #006080;">"ADODB.Recordset"</span> )

oConn.Open <span style="color: #006080;">"QT_Flight32"</span>
oRst.CursorLocation = adUseClient
sql = <span style="color: #006080;">"SELECT * FROM Orders"</span>
oRst.Open sql, oConn, adOpenStatic, adLockOptimistic
searchCriteria = <span style="color: #006080;">"Order_Number = 12"</span>
oRst.Find searchCriteria
oRst.Delete
oRst.Close : oConn.Close

 

, ,