Solved

SelectNodes not work??

Posted on 2001-06-15
14
720 Views
Last Modified: 2010-05-18
I have the following statement in an ASP page
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).value = "./*[position() < " & iRecordsPerPage + 1 & " and position() > 0]"

What is happening when this code is being executed is that Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).value is evaluating to nothing.

Here is the XSL that is being referenced.  You will notice about half way down it clearly says <xsl:for-each select="...">, so I don't know why the SelectNodes above is not working.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:user-namespace-here" version="1.0">

<msxsl:script language="VBScript" implements-prefix="user">
      <![CDATA[
            function getName(node)
                  getName = node.item(0).NodeName
            end function
      ]]>
</msxsl:script>

<xsl:template match="/">
      <xsl:apply-templates select="/*" />
</xsl:template>

<xsl:template match="/*">
      <table width="100%">
            <tr>
                  <td align="left" valign="bottom"><b>Page <span id="CurrentPage"></span>&#160; of &#160;<span id="PageCount"></span>.  Total PODs: <span id="RecordCount"></span>&#160;</b></td>
                  <td align="right"><b>PODs Per Page: <input onblur="setRecordsPerPage()" id="RecordsPerPage" type="text" size="2"></input></b></td>
                  <td align="right" valign="bottom">
                        <span id="Paging" style="Display:">
                              <input type="button" OnClick="FirstPage()"><xsl:attribute name="value"><![CDATA[|<]]></xsl:attribute></input>
                              <input type="button" OnClick="PreviousPage(1)"><xsl:attribute name="value"><![CDATA[<]]></xsl:attribute></input>
                              <input type="button" OnClick="NextPage(1)" value=">"></input>
                              <input type="button" OnClick="LastPage()" value=">|"></input>
                        </span>
                  </td>
            </tr>
      </table>
      
      <table width="100%" border="1" topmargin="0" leftmargin="0" cellpadding="0" cellspacing="0">
            <tr style="cursor: hand">
                  <td bgcolor="#CCFFFF" onclick="Sort('DATEREQUESTED')"><b><u><nobr>Requested On</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('PERSONREQUESTED')"><b><u><nobr>Requested By</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('PLANTID')"><b><u><nobr>Plant</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('SHIPDATE')"><b><u><nobr>Shipped On</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('DELIVERYDATE')"><b><u><nobr>Delivered On</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('ORDERNUMBER')"><b><u><nobr>Order Number</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('SLIMVMT')"><b><u><nobr>SLI MVMT #</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('CUSTNAME')"><b><u><nobr>Customer</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('CITY')"><b><u><nobr>City</nobr></u></b></td>
                  <td bgcolor="#CCFFFF" onclick="Sort('STATE')"><b><u><nobr>State</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('PERSONOBTAINING')"><b><u><nobr>Obtained By</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('SCACID')"><b><u><nobr>SCAC</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('FIRSTCARRIER')"><b><u><nobr>First Carrier</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('SECONDCARRIER')"><b><u><nobr>Second Carrier</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('THIRDCARRIER')"><b><u><nobr>Third Carrier</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('PODRECEIVED')"><b><u><nobr>POD Received</nobr></u></b></td>
                  <td bgcolor="#CCFFCC" onclick="Sort('SLISHIPTOOSCDATE')"><b><u><nobr>SLI Ship To OSC</nobr></u></b></td>
                  <td onclick="Sort('OSCRECEIVEDDATE')"><b><u><nobr>OSC Received</nobr></u></b></td>
                  <td onclick="Sort('COMMENTS')"><b><u><nobr>Comments</nobr></u></b></td>
            </tr>
            <xsl:for-each select="./*[position() &#60; 6 and position() &#62; 0]">
                  <xsl:sort select="./*[1]" order="ascending" />
                  <tr>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="DATEREQUESTED" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="PERSONREQUESTED" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="PLANTID" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="SHIPDATE" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="DELIVERYDATE" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="ORDERNUMBER" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="SLIMVMT" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="CUSTNAME" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="CITY" /></td>
                        <td bgcolor="CCFFFF">&#160;<xsl:value-of select="STATE" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="PERSONOBTAINING" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="SCACID" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="FIRSTCARRIER" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="SECONDCARRIER" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="THIRDCARRIER" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="PODRECEIVED" /></td>
                        <td bgcolor="CCFFCC">&#160;<xsl:value-of select="SLISHIPTOOSCDATE" /></td>
                        <td>&#160;<xsl:value-of select="OSCRECEIVEDDATE" /></td>
                        <td>&#160;<xsl:value-of select="COMMENTS" /></td>
                  </tr>
            </xsl:for-each>
      </table>
</xsl:template>
      
</xsl:stylesheet>
0
Comment
Question by:Jagar
  • 9
  • 5
14 Comments
 
LVL 3

Expert Comment

by:dragosh
ID: 6195141
what do you want to do ??? retreive xsl:for-each nodes from this XSL document ???
0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195201
maybe if you can try something like

Style.XMLDocument.selectNodes("//xsl:for-each")

because "xsl:for-each" is the name of the tag, and "select" is an attribute.

and this will you will retreive the node and to access his attribute and set a value write like :

Style.XMLDocument.selectNodes("//xsl:for-each").setAttribute "select", <<value>>

rgds
0
 
LVL 2

Author Comment

by:Jagar
ID: 6195265
   I tried doing just //xsl:for-each and that returns as nothing as well.  What I'm doing is that setting up paging of a table, so that it only display say 20 records per page and the user can move through the pages as needed.

    Here is an example of the HTML page.  Note you will need the latest version of the Microsoft XML parser for this work:
<HTML>
<Head>
<LINK rel="stylesheet" type="text/css" href="../General.css">
<Script language="vbscript">
option explicit
Dim iRecordsPerPage

iRecordsPerPage = 20

Function Window_Onload()

      ' Adjust the record level loop so that it displays our default number of records per page
      Style.XMLDocument.SelectNodes("//xsl:for-each")(1).value = "./*[position() < " & iRecordsPerPage + 1 & " and position() > 0]"      

      transform()
      
      setPageCount()
      
End function

Function Transform()
      'Transform the xml document and stylesheet and display the # of records
      'per page
      DisplayArea.innerHTML = xmlMasterData.transformNode(Style.DocumentElement)
      
      RecordsPerPage.value = iRecordsPerPage
End function

Function redisplay(iPage)
      'Transform the document and display status info

      Dim sDisplay
      Dim iPageCount
      Dim iRecordCount      
      
      'Store status information for use after
      'the transformation because it gets lost
      'in the transformation
      iPageCount = PageCount.innerHTML
      
      iRecordCount = RecordCount.innerHTML

      transform()
      
      'Display status information
      PageCount.innerHTML = iPageCount
      RecordCount.innerHTML = iRecordCount
      CurrentPage.innerHTML = iPage
end function

function Sort(sField)
      'Change the sort order and redisplay
      Dim sortField
      Dim sortOrderAttribute
      
      'Attach to the order-by attribute                                    
      set sortField = Style.XMLDocument.selectSingleNode("//xsl:sort/@select")                        
      'Attach to the sort order attribute
      set sortOrderAttribute = Style.XMLDocument.selectSingleNode("//xsl:sort/@order")
                                                                              
      'If we are already sorting by sField
      if sortField.value = sField or sortField.value = "./*[0]" then                                                
            'change the sort order
            if sortOrderAttribute.value = "descending" then
                  sortOrderAttribute.value = "ascending"
            else
                  sortOrderAttribute.value = "descending"
            end if                        
      else
            'sort ascending                                    
            sortField.value = sField            
            sortOrderAttribute.value = "ascending"
      end if
      
      set sortField = nothing
      set sortOrderAttribute = nothing
      
      redisplay(CurrentPage.innerHTML)                                                                  
end function

function setRecordsPerPage()
      'Reset the number of records per page

      if isnumeric(RecordsPerPage.value) then
            iRecordsPerPage = cint(RecordsPerPage.value)
            window_onload
      end if
end function

function setPageCount()
      'Display page count status information
      Dim iTotalRecords
      
      PageCount.innerHTML = getNumberOfPages(iTotalRecords)
      
      RecordCount.innerHTML = iTotalRecords
      
      CurrentPage.innerHTML = 1
end function

function getNumberOfPages(iTotalRecords)      
      'Calculate and return the total number of pages
      'and total number of records
      Dim iPages

      'Use the length property to get the record count
      iTotalRecords = xmlMasterData.XMLDocument.selectNodes("/*/*").length                  
      
      'Calculate the total number of pages
      iPages = iTotalRecords/iRecordsPerPage      
      
      if instr(iPages, ".") > 0 then
            iPages = cint(left(iPages, instr(iPages, "."))) + 1
      end if
      
      getNumberOfPages = iPages
end function

function nextPage(iPage)
      Dim sDisplay
      Dim sDateRange      
      
      'Only make changes if we aren't on the last page
      if cint(cstr(iPage) * iRecordsPerPage) <  xmlMasterData.selectNodes("/*/*").length then                                    
            iPage = cint(iPage) + 1
            'Set the new onClick event value for the previous page button
            Style.XMLDocument.selectNodes("//@OnClick")(1).value = "previousPage(" & iPage & ")"                                                      
            
            'Set the new onClick even value for the nextpage button                        
            Style.XMLDocument.selectNodes("//@OnClick")(2).value = "nextPage(" & iPage & ")"                  
            
            'Set the new values for the record level loop                  
            Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).value = "./*[position() <= " & (cstr(iPage) * iRecordsPerPage) & " and position() > " & (cint(iPage) - 1) * iRecordsPerPage & "]"

            redisplay(iPage)                                                
      end if      
end function

function previousPage(iPage)
      Dim sDisplay
      Dim sDateRange      
      
      'If we aren't on the first page
      if iPage > 1 then
            iPage = cint(iPage) - 1            
      
            'Set the new onClick event value for the previous page button
            Style.XMLDocument.selectNodes("//@OnClick")(1).value = "previousPage(" & iPage & ")"            
            'Set the new onClick even value for the nextpage button
            Style.XMLDocument.selectNodes("//@OnClick")(2).value = "nextPage(" & iPage & ")"                  
            
            'Set the new values for the record level loop                  
            Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).value = "./*[position() <= " & (cstr(iPage) * iRecordsPerPage) & " and position() > " & (cint(iPage) - 1) * iRecordsPerPage & "]"
            
            redisplay(iPage)
      end if
end function

function FirstPage()
      'Set the new onClick event value for the previous page button
      Style.XMLDocument.selectNodes("//@OnClick")(1).value = "previousPage(1)"            

      'Set the new onClick even value for the nextpage button
      Style.XMLDocument.selectNodes("//@OnClick")(2).value = "nextPage(1)"                  

      'Set the new values for the record level loop            
      Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).value = "./*[position() < " & iRecordsPerPage + 1 & " and position() > 0]"      
      
      transform()
      
      setPageCount()                                          
end function

function LastPage()
      Dim iTotalPages
      Dim iTotalRecords
      
      'Calculate the number of pages
      iTotalPages = getNumberOfPages(iTotalRecords)
      
      'Call next page, passing the total pages minus 1
      nextPage(iTotalPages - 1)                                                      
end function

function EditPage(iPODID)
      'We can't let anybody edit these PODs
      EditPage = false
end function
</Script>
</Head>
<body>
<XML id='xmlMasterData'> <recordset><row><PODREQUESTID>17</PODREQUESTID><DATEREQUESTED>2001-06-14</DATEREQUESTED><PERSONREQUESTED>Paul  Cavacas</PERSONREQUESTED><PLANTID>600</PLANTID><SHIPDATE>2000-11-28</SHIPDATE><DELIVERYDATE>2000-11-30</DELIVERYDATE><ORDERNUMBER>224983</ORDERNUMBER><SLIMVMT>AA20846</SLIMVMT><CUSTNAME>PUBLIX - BOYNTON BEACH</CUSTNAME><CITY>BOYNTON BEACH</CITY><STATE>FL</STATE><PERSONOBTAINING>Paul  Cavacas</PERSONOBTAINING><SCACID>ANTT</SCACID><FIRSTCARRIER>2001-04-05</FIRSTCARRIER><PODRECEIVEDDATE>2001-04-08</PODRECEIVEDDATE><SLISHIPTOOSCDATE>2001-04-09</SLISHIPTOOSCDATE><OSCRECEIVEDDATE>2001-07-12</OSCRECEIVEDDATE><COMMENTS>Here are some comments.</COMMENTS></row><row><PODREQUESTID>18</PODREQUESTID><DATEREQUESTED>2001-06-15</DATEREQUESTED><PERSONREQUESTED>Paul  Cavacas</PERSONREQUESTED><PLANTID>600</PLANTID><SHIPDATE>2000-12-01</SHIPDATE><DELIVERYDATE>2000-12-07</DELIVERYDATE><ORDERNUMBER>224982</ORDERNUMBER><SLIMVMT>AA35678</SLIMVMT><CUSTNAME>MCLANE</CUSTNAME><CITY>BROOKHAVEN</CITY><STATE>MS</STATE><PERSONOBTAINING>Paul  Cavacas</PERSONOBTAINING><SCACID>CENF</SCACID><FIRSTCARRIER>2001-04-05</FIRSTCARRIER><SECONDCARRIER>2001-04-06</SECONDCARRIER><THIRDCARRIER>2001-04-07</THIRDCARRIER><PODRECEIVEDDATE>2001-04-08</PODRECEIVEDDATE><SLISHIPTOOSCDATE>2001-04-09</SLISHIPTOOSCDATE><OSCRECEIVEDDATE>2001-07-12</OSCRECEIVEDDATE><COMMENTS>Done</COMMENTS></row><row><PODREQUESTID>14</PODREQUESTID><DATEREQUESTED>2001-06-14</DATEREQUESTED><PERSONREQUESTED>Paul  Cavacas</PERSONREQUESTED><PLANTID>743</PLANTID><SHIPDATE>2000-11-27</SHIPDATE><DELIVERYDATE>2000-11-28</DELIVERYDATE><ORDERNUMBER>224996</ORDERNUMBER><SLIMVMT>AA18866</SLIMVMT><CUSTNAME>COASTAL PACIFIC FOOD DISTRIBUTORS</CUSTNAME><CITY>STOCKTON</CITY><STATE>CA</STATE><PERSONOBTAINING></PERSONOBTAINING><SCACID>BSRK</SCACID><COMMENTS>Here are some comments.</COMMENTS></row><row><PODREQUESTID>15</PODREQUESTID><DATEREQUESTED>2001-06-14</DATEREQUESTED><PERSONREQUESTED>Paul  Cavacas</PERSONREQUESTED><PLANTID>104</PLANTID><SHIPDATE>2000-11-20</SHIPDATE><ORDERNUMBER>224987</ORDERNUMBER><SLIMVMT></SLIMVMT><CUSTNAME>BIG Y FOODS INC</CUSTNAME><CITY>SPRINGFIELD</CITY><STATE>MA</STATE><PERSONOBTAINING>Paul  Cavacas</PERSONOBTAINING><SCACID>NCLS</SCACID><FIRSTCARRIER>2001-04-05</FIRSTCARRIER><SECONDCARRIER>2001-04-06</SECONDCARRIER><PODRECEIVEDDATE>2001-04-08</PODRECEIVEDDATE><SLISHIPTOOSCDATE>2001-04-09</SLISHIPTOOSCDATE><OSCRECEIVEDDATE>2001-07-12</OSCRECEIVEDDATE></row><row><PODREQUESTID>16</PODREQUESTID><DATEREQUESTED>2001-06-14</DATEREQUESTED><PERSONREQUESTED>Paul  Cavacas</PERSONREQUESTED><PLANTID>600</PLANTID><SHIPDATE>2000-11-25</SHIPDATE><ORDERNUMBER>224986</ORDERNUMBER><SLIMVMT>224986</SLIMVMT><CUSTNAME>THE HE BUTT GROC CO</CUSTNAME><CITY>SAN ANTONIO</CITY><STATE>TX</STATE><PERSONOBTAINING>Paul  Cavacas</PERSONOBTAINING><SCACID>PIUP</SCACID><FIRSTCARRIER>2001-04-05</FIRSTCARRIER><SECONDCARRIER>2001-04-06</SECONDCARRIER><THIRDCARRIER>2001-04-07</THIRDCARRIER><PODRECEIVEDDATE>2001-04-08</PODRECEIVEDDATE><SLISHIPTOOSCDATE>2001-04-09</SLISHIPTOOSCDATE><COMMENTS>More Comments for a POD</COMMENTS></row></recordset>
</XML><XML id='Style' src='../XSLT/AllPODS.xslt'></XML><span id='DisplayArea'></span> </body>
</HTML>

0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195329
hmm . i think a know a better solution .. don't modify your xsl , let it as it is .. your problem is to load only 20 nodes from your xml .. how do you do that ?

You have your XML and you want to select from it only 20 records, "row" elements.

let's say you have also a pointer = page number

make a select for "//row" and you will retreive all row nodes. after that you will select just the nodes you want like this :

Dim rowNode
Dim rowNodes
Dim newXMLString   ' here you will find 20 row nodes
Dim i              ' counter
Dim k              ' counter for the 20 records
Dim pageNumber     ' page number
Dim pagesize       ' page size = 20

pagesize = 20
pagenumber = 3
i = 1
k = 0

'will have to step over 20*2 = 60 rows

Set rowNodes = <yourXMLObject>.selctNodes("//row")

newXMLString = "<recordset>"

For Each rowNode In rowNode
  If i < pagesize*pagenumber Then
     ' do nothing
  Else
     k = k + 1
     newXMLString = newXMLString  & rowNode.xml
  End If
  i = i + 1
Next

newXMLString = newXMLString  & "</recordset>"

and now in newXMLString string you have only 20 or less row

hope this will help

rgds
0
 
LVL 2

Author Comment

by:Jagar
ID: 6195339
I would rather return the whole XML to the client and let them handle it the page instead of having to continue to hit the server for each page.
0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195345
and one more thing .. don't forget to test for
( K <= pagesize )    ... !!!!
0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195350
it's like when you are paging through a recordset ..
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 3

Expert Comment

by:dragosh
ID: 6195386
regarding your code the function :

Function Window_Onload()

     ' Adjust the record level loop so that it displays our default number of records per page
     Style.XMLDocument.SelectNodes("//xsl:for-each")(1).value = "./*[position() < " & iRecordsPerPage +
1 & " and position() > 0]"    

     transform()
     
     setPageCount()
     
End function


you want to set the value for the "select" attribute . not like this , i told you :

Style.XMLDocument.selectNodes("//xsl:for-each").setAttribute "select", "./*[position() < " & iRecordsPerPage +
1 & " and position() > 0]"

0
 
LVL 2

Author Comment

by:Jagar
ID: 6195404
Style.XMLDocument.selectNodes("//xsl:for-each").setAttribute "select", "./*[position() < " & iRecordsPerPage
+
1 & " and position() > 0]"

doesn't work.  This is still not returning anything.
0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195455
I tried your search , like this :

Dim obj
Set obj = Server.CreateObject("MSXML2.DOMDocument")
obj.load Server.MapPath ("test.xsl")
Response.Write Server.HTMLEncode(obj.selectNodes("//xsl:for-each").item(0).xml)
Response.Write obj.selectNodes("//xsl:for-each").length

where test.xsl is your XSL document.
Results -> 1 node !!!!

try to verify the results of your search
0
 
LVL 2

Author Comment

by:Jagar
ID: 6195514
I copied your example above and got the expected results.  Now you try using the HTML page that I posted and the XSLT source that I posted and you will see that it doesn't work when I do it this way.
0
 
LVL 3

Accepted Solution

by:
dragosh earned 150 total points
ID: 6195549
good news .. i copied your code and test it !!! GOOD NEWS !

it's working .. with a few changes .. try this function for example :

Function Window_Onload()

     ' Adjust the record level loop so that it displays our default number of records per page
     msgbox(Style.XMLDocument.SelectNodes("//xsl:for-each").length)
     msgbox(Style.XMLDocument.SelectNodes("//xsl:for-each").item(0).xml)
     Style.XMLDocument.SelectNodes("//xsl:for-each")(0).setAttribute "select", "./*[position() < " & iRecordsPerPage + 1 & " and position() > 0]"

     transform()
     
     setPageCount()
     
End function


i will have to correct the rest of your code

rgds
0
 
LVL 2

Author Comment

by:Jagar
ID: 6195568
 Thank You I've changed the rest of the code.
0
 
LVL 3

Expert Comment

by:dragosh
ID: 6195582
thnaks for the points :)
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now