使用每个数据组的唯一 header 行组织 HTML table 中的 JSON 数据

Organize JSON data in HTML table with unique header rows for each data group

我有一个 JSON object,其中包括一个 key:value 对 callRoot。此 key:value 对的示例值包括 @S@C@W .有多个 object 具有相同的值,我希望在每个分组的开头设置一个 HTML table 标题行,并为每组数据重复它。

更新

获取 API 函数以访问远程 API 数据:

const fetchData = function() {
  const apiKey = "";
  const request = `https://apiurl.com`;

  fetch(request)
    .then(response => response.json())
    .then((data) => foo(data))
    .catch(error => {
      console.log(error);
    });
  }
fetchData();

更新二

for (let i of filtered[property]) {
  const tr = document.createElement('tr');
  tblBody.appendChild(tr);
  data.forEach(element => {
    console.log(element);
  });

示例 JSON 数据:

const data = [
  {
    "symbol": {
      "description": "SOYBEANS January 2022"
    },
    "actualSymbol": "@SF22",
    "high": {
      "number": 1396
    },
    "low": {
      "number": 1374.75
    },
    "close": null,
    "settlePrice": {
      "number": 1401.5
    },
    "last": {
      "number": 1378
    },
    "change": {
      "number": -23.5
    },
    "month": "Jan 22",
    "callRoot": "@S",
    "userDescription": "SOYBEANS",
  },
  {
    "symbol": {
      "description": "SOYBEANS March 2022"
    },
    "actualSymbol": "@SH22",
    "high": {
      "number": 1409.75
    },
    "low": {
      "number": 1379
    },
    "close": null,
    "settlePrice": {
      "number": 1410.25
    },
    "last": {
      "number": 1383.25
    },
    "change": {
      "number": -27
    },
    "month": "Mar 22",
    "callRoot": "@S",
    "userDescription": "SOYBEANS",
  },
  {
  "symbol": {
    "description": "SOYBEANS May 2022",
   },
  "actualSymbol": "@SK22",
  "high": {
    "number": 1418
  },
  "low": {
    "number": 1387.5
  },
  "close": null,
  "settlePrice": {
    "number": 1418.75
  },
  "last": {
    "number": 1391.25
  },
  "change": {
    "number": -27.5
  },
  "month": "May 22",
  "callRoot": "@S",
  "userDescription": "SOYBEANS",
},
{
  "symbol": {
    "description": "CORN March 2022",
  },
  "actualSymbol": "@CH22",
  "high": {
    "number": 608
  },
  "low": {
    "number": 596.75
  },
  "close": null,
  "settlePrice": {
    "number": 606.75
  },
  "last": {
    "number": 599.25
  },
  "change": {
    "number": -7.5
  },
  "month": "Mar 22",
  "callRoot": "@C",
  "userDescription": "CORN",
},
{
  "symbol": {
    "description": "CORN May 2022",
  },
  "actualSymbol": "@CK22",
  "high": {
    "number": 608.5
  },
  "low": {
    "number": 598.25
  },
  "close": null,
  "settlePrice": {
    "number": 607.75
  },
  "last": {
    "number": 600.75
  },
  "change": {
    "number": -7
  },
  "month": "May 22",
  "callRoot": "@C",
  "userDescription": "CORN",
},
{
  "symbol": {
    "description": "CORN July 2022",
  },
  "actualSymbol": "@CN22",
  "high": {
    "number": 605.25
  },
  "low": {
    "number": 595.5
  },
  "close": null,
  "settlePrice": {
    "number": 604.5
  },
  "last": {
    "number": 598
  },
  "change": {
    "number": -6.5
  },
  "month": "Jul 22",
  "callRoot": "@C",
  "userDescription": "CORN",
},
{
  "symbol": {
    "description": "WHEAT March 2022",
  },
  "actualSymbol": "@WH22",
  "high": {
    "number": 767.5
  },
  "low": {
    "number": 748
  },
  "close": null,
  "settlePrice": {
    "number": 758.5
  },
  "last": {
    "number": 763.75
  },
  "change": {
    "number": 5.25
  },
  "month": "Mar 22",
  "callRoot": "@W",
  "userDescription": "WHEAT",
},
{
  "symbol": {
    "description": "WHEAT May 2022",
  },
  "actualSymbol": "@WK22",
  "high": {
    "number": 768.5
  },
  "low": {
    "number": 750
  },
  "close": null,
  "settlePrice": {
    "number": 760.5
  },
  "last": {
    "number": 765.5
  },
  "change": {
    "number": 5
  },
  "month": "May 22",
  "callRoot": "@W",
  "userDescription": "WHEAT",
},
{
  "symbol": {
    "description": "WHEAT July 2022",
  },
  "actualSymbol": "@WN22",
  "high": {
    "number": 763.25
  },
  "low": {
    "number": 747.25
  },
  "close": null,
  "settlePrice": {
    "number": 757
  },
  "last": {
    "number": 760.5
  },
  "change": {
    "number": 3.5
  },
  "month": "Jul 22",
  "callRoot": "@W",
  "userDescription": "WHEAT",
}

];

这是我一直在玩的一些代码,尽管我可能无法实现我的设定要求。 switch 语句可能比 if/else if statement

更适合
// Create empty arrays for each callRoot grouping
const soybeans = [];
const corn = [];
const wheat = [];

for(let commodity of commodities) {
  let callRoot = commodity.callRoot;
  if(callRoot.includes("@S")) {

  } else if(callRoot.includes("@C")) {

  } else if(callRoot.includes("@W")) {
  
  }
}

const soyHeader = soybean[0];
if(soyHeader) {
  // Render table header row HTML
}
// Render table row HTML

const cornHeader = corn[0];
if(cornHeader) {
  // Render table header row HTML
}
// Render table row HTML

const wheatHeader = wheat[0];
if(wheatHeader) {
  // Render table header row HTML
}
// Render table row HTML

示例HTML table结构:

<table>
  <tbody>
    <tr>
      <th colspan="9">SOYBEANS</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="9">CORN</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="9">WHEAT</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
</table>

我试图创建一个函数,它根据你的示例table创建了

这是我的 script/function:

旧函数数据错误但输出正确.-.

const filterData = function (data) {
    const filtered = {};
    data.forEach(element => { // going through all the elements
        if (filtered[element.callRoot]) filtered[element.callRoot].push(element); // if callRoot already exists in filtered object
        else filtered[element.callRoot] = [element]; // else create property with callRoot as name -> here we push all the objects with the same callRoot name
    })
    return filtered;
};

const foo = function (data, element) {
    const filtered = filterData(data);

    // starting to create Table

    // creating static table element, here becomes the element argument useful
    const table = document.createElement('table');
    element.appendChild(table);

    // now we start creating the tbodies, trs and tds with the filtered data

    // so we go through our filtered object by looping through an array of the keys ('@S','@C','@W')
    Object.keys(filtered).forEach(property => {

        // for each property we will create the tbody and tr + th and append them
        const tbody = document.createElement('tbody');
        table.appendChild(tbody);
        let tr = document.createElement('tr');
        tbody.appendChild(tr);
        const th = document.createElement('th');
        th.setAttribute('colspan', 9); // adding colspan attribute
        th.textContent = filtered[property][0].userDescription; // taking the description as th text
        tr.appendChild(th);

        // now we create the rest of the tbody

        // since i dont know where the data for the table comes from i will use the defined data from your example html output

        // creating tr for our header tds
        tr = document.createElement('tr');
        tbody.appendChild(tr);
        const definedDataArrayHeaders = ['Month', 'Last', 'Change', 'High', 'Low']; // headers from your example
        definedDataArrayHeaders.forEach(element => { // going through the headers
            const td = document.createElement('td');
            td.textContent = element; // writing the header inside the td
            tr.appendChild(td);
        });

        const definedDataArrayTds = ['August 2022', "1265'2", "-2'4", "1275'2", "1261'4"]; // tds from your example
        for (let i of filtered[property]) { // will loop through each object inside our filtered array -> each tr in our future table
            const tr = document.createElement('tr'); // creating tr for each data
            tbody.appendChild(tr);
            definedDataArrayTds.forEach(element => { // looping through the td data
                const td = document.createElement('td');
                td.textContent = element; // writing the data inside the td
                tr.appendChild(td);
            })
        }
    })


}

foo(commodities, document.querySelector('div')); // calling the function with data and Element where the table should be appended to

FALSE 旧使用数据:

const commodities = [
    {
        actualSymbol: "@SF22",
        callRoot: "@S",
        open: 1.00,
        close: 2.00,
        userDescription: "SOYBEANS",
        // Other data
    },
    {
        actualSymbol: "@SH22",
        callRoot: "@S",
        open: 4.00,
        close: 6.00,
        userDescription: "SOYBEANS",
        // Other data
    },
    {
        actualSymbol: "@SK22",
        callRoot: "@S",
        open: 0.50,
        close: 2.30,
        userDescription: "SOYBEANS",
        // Other data
    },
    {
        actualSymbol: "@CH22",
        callRoot: "@C",
        open: 0.25,
        close: 0.75,
        userDescription: "CORN",
        // Other data
    },
    {
        actualSymbol: "@CK22",
        callRoot: "@C",
        open: 5.00,
        close: 6.75,
        userDescription: "CORN",
        // Other data
    },
    {
        actualSymbol: "@CN22",
        callRoot: "@C",
        open: 1.00,
        close: 2.00,
        userDescription: "CORN",
        // Other data
    },
    {
        actualSymbol: "@WH22",
        callRoot: "@W",
        open: 3.25,
        close: 2.00,
        userDescription: "WHEAT",
        // Other data
    },
    {
        actualSymbol: "@WK22",
        callRoot: "@W",
        open: 1.00,
        close: 2.00,
        userDescription: "WHEAT",
        // Other data
    },
    {
        actualSymbol: "@WN22",
        callRoot: "@W",
        open: 0.10,
        close: 0.20,
        userDescription: "WHEAT",
        // Other data
    }
];

但是对于正确的示例输出,这是 html 输出:

<div>
    <table>
        <tbody>
            <tr>
                <th colspan="9">SOYBEANS</th>
            </tr>
            <tr>
                <td>Month</td>
                <td>Last</td>
                <td>Change</td>
                <td>High</td>
                <td>Low</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
        </tbody>
        <tbody>
            <tr>
                <th colspan="9">CORN</th>
            </tr>
            <tr>
                <td>Month</td>
                <td>Last</td>
                <td>Change</td>
                <td>High</td>
                <td>Low</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
        </tbody>
        <tbody>
            <tr>
                <th colspan="9">WHEAT</th>
            </tr>
            <tr>
                <td>Month</td>
                <td>Last</td>
                <td>Change</td>
                <td>High</td>
                <td>Low</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
            <tr>
                <td>August 2022</td>
                <td>1265'2</td>
                <td>-2'4</td>
                <td>1275'2</td>
                <td>1261'4</td>
            </tr>
        </tbody>
    </table>
</div>

新解决方案,希望这个能正常工作哈哈

这里是新版的脚本,肯定不好,就当是自己的攻略吧

const filterData2 = function (data) {
    const filtered = {};
    const wantedData = ['month', 'change', 'last', 'high', 'low', 'settlePrice'];
    data.forEach(element => { // going through all the elements
        // now using userDescript as key since its a bit more precise
        if (filtered[element.userDescription]) { // if userDescription already exists in filtered object
            const piece = [];
            // now we extract only the data we need for our html table:
            Object.entries(element).forEach(array => {
                if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
            });
            filtered[element.userDescription].push(piece);
        }
        else {// else create property with userDescription as name -> here we push all the objects with the same callRoot name
            const piece = [];
            filtered[element.userDescription] = [];
            Object.entries(element).forEach(array => {
                if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
            });
            filtered[element.userDescription].push(piece);
        }
    })
    return filtered;
};


// needed since i structured my filtered data different
const getValue = (arr, string) => arr.find(pair => pair[0] === string);

const foo2 = function (data, element) {
    const filtered = filterData2(data);

    // starting to create Table

    // creating static table element, here becomes the element argument useful
    const table = document.createElement('table');
    element.appendChild(table);

    // now we start creating the tbodies, trs and tds with the filtered data

    // so we go through our filtered object by looping through an array of the keys in example:('SOYBEANS','CORN','WHEAT')
    Object.keys(filtered).forEach(key => {

        // key will be either 'SOYBEANS', 'CORN', 'WHEAT' - in this example in exactly this order

        // for each key we will create the tbody and tr + th and append them
        const tbody = document.createElement('tbody');
        table.appendChild(tbody);
        let tr = document.createElement('tr'); // using let here since we are going to overwrite this variable later so we dont have to create a new one
        tbody.appendChild(tr);
        const th = document.createElement('th');
        th.setAttribute('colspan', 9); // adding colspan attribute
        th.textContent = key; // taking the key as a header
        tr.appendChild(th);

        // now we create the rest of the tbody

        // now since we filtered the data so in our filtered variable are only the necessary values for our table except the Settle Date

        // creating tr for our header tds
        tr = document.createElement('tr');
        tbody.appendChild(tr);
        const definedDataArrayHeaders = ['MONTH', 'LAST', 'CHANGE', 'HIGH', 'LOW', 'SETTLE DATE', 'SETTLE PRICE', 'MORE']; // Headers for the Table, can be anything - keep in Mind the date must be coming from somewhere for these headers, just some are covered by the filtered Array
        definedDataArrayHeaders.forEach(header => { // going through the headers
            const td = document.createElement('td');
            td.textContent = header; // writing the header inside the td
            tr.appendChild(td); // tr we created outside, so they all come into the same row
        });

        const definedDataArrayTds = ['month', "last", "change", "high", "low", "missing", "settlePrice", "missing"]; // this array must contain the names of the values inside the filtered array and must be in the same order as "definedDataArrayHeaders" so the data is in the right column

        // since the Settle date and more value arent in the data/filtered array i will take placeholders so the table still renders right

        // this part is needed to be changed a lot, since the data is now structured completely different

        for (let i of filtered[key]) { // will loop through each object inside our filtered array -> each tr in our future table
            const tr = document.createElement('tr'); // creating tr for each data
            tbody.appendChild(tr);
            definedDataArrayTds.forEach(element => { // looping through the td data
                const td = document.createElement('td');
                td.textContent = getValue(i, element)?.[1] || 'PLACEHOLDER'; // writing the data inside the td
                tr.appendChild(td);
            })
        }
    })
}

foo2(data, document.querySelector('div'));

此新示例中使用的数据:

const data = [
    {
        "symbol": {
            "description": "SOYBEANS January 2022"
        },
        "actualSymbol": "@SF22",
        "high": {
            "number": 1396
        },
        "low": {
            "number": 1374.75
        },
        "close": null,
        "settlePrice": {
            "number": 1401.5
        },
        "last": {
            "number": 1378
        },
        "change": {
            "number": -23.5
        },
        "month": "Jan 22",
        "callRoot": "@S",
        "userDescription": "SOYBEANS",
    },
    {
        "symbol": {
            "description": "SOYBEANS March 2022"
        },
        "actualSymbol": "@SH22",
        "high": {
            "number": 1409.75
        },
        "low": {
            "number": 1379
        },
        "close": null,
        "settlePrice": {
            "number": 1410.25
        },
        "last": {
            "number": 1383.25
        },
        "change": {
            "number": -27
        },
        "month": "Mar 22",
        "callRoot": "@S",
        "userDescription": "SOYBEANS",
    },
    {
        "symbol": {
            "description": "SOYBEANS May 2022",
        },
        "actualSymbol": "@SK22",
        "high": {
            "number": 1418
        },
        "low": {
            "number": 1387.5
        },
        "close": null,
        "settlePrice": {
            "number": 1418.75
        },
        "last": {
            "number": 1391.25
        },
        "change": {
            "number": -27.5
        },
        "month": "May 22",
        "callRoot": "@S",
        "userDescription": "SOYBEANS",
    },
    {
        "symbol": {
            "description": "CORN March 2022",
        },
        "actualSymbol": "@CH22",
        "high": {
            "number": 608
        },
        "low": {
            "number": 596.75
        },
        "close": null,
        "settlePrice": {
            "number": 606.75
        },
        "last": {
            "number": 599.25
        },
        "change": {
            "number": -7.5
        },
        "month": "Mar 22",
        "callRoot": "@C",
        "userDescription": "CORN",
    },
    {
        "symbol": {
            "description": "CORN May 2022",
        },
        "actualSymbol": "@CK22",
        "high": {
            "number": 608.5
        },
        "low": {
            "number": 598.25
        },
        "close": null,
        "settlePrice": {
            "number": 607.75
        },
        "last": {
            "number": 600.75
        },
        "change": {
            "number": -7
        },
        "month": "May 22",
        "callRoot": "@C",
        "userDescription": "CORN",
    },
    {
        "symbol": {
            "description": "CORN July 2022",
        },
        "actualSymbol": "@CN22",
        "high": {
            "number": 605.25
        },
        "low": {
            "number": 595.5
        },
        "close": null,
        "settlePrice": {
            "number": 604.5
        },
        "last": {
            "number": 598
        },
        "change": {
            "number": -6.5
        },
        "month": "Jul 22",
        "callRoot": "@C",
        "userDescription": "CORN",
    },
    {
        "symbol": {
            "description": "WHEAT March 2022",
        },
        "actualSymbol": "@WH22",
        "high": {
            "number": 767.5
        },
        "low": {
            "number": 748
        },
        "close": null,
        "settlePrice": {
            "number": 758.5
        },
        "last": {
            "number": 763.75
        },
        "change": {
            "number": 5.25
        },
        "month": "Mar 22",
        "callRoot": "@W",
        "userDescription": "WHEAT",
    },
    {
        "symbol": {
            "description": "WHEAT May 2022",
        },
        "actualSymbol": "@WK22",
        "high": {
            "number": 768.5
        },
        "low": {
            "number": 750
        },
        "close": null,
        "settlePrice": {
            "number": 760.5
        },
        "last": {
            "number": 765.5
        },
        "change": {
            "number": 5
        },
        "month": "May 22",
        "callRoot": "@W",
        "userDescription": "WHEAT",
    },
    {
        "symbol": {
            "description": "WHEAT July 2022",
        },
        "actualSymbol": "@WN22",
        "high": {
            "number": 763.25
        },
        "low": {
            "number": 747.25
        },
        "close": null,
        "settlePrice": {
            "number": 757
        },
        "last": {
            "number": 760.5
        },
        "change": {
            "number": 3.5
        },
        "month": "Jul 22",
        "callRoot": "@W",
        "userDescription": "WHEAT",
    }
];

用上面的数据例子输出

<div>
    <table>
        <tbody>
            <tr>
                <th colspan="9">SOYBEANS</th>
            </tr>
            <tr>
                <td>MONTH</td>
                <td>LAST</td>
                <td>CHANGE</td>
                <td>HIGH</td>
                <td>LOW</td>
                <td>SETTLE DATE</td>
                <td>SETTLE PRICE</td>
                <td>MORE</td>
            </tr>
            <tr>
                <td>Jan 22</td>
                <td>1378</td>
                <td>-23.5</td>
                <td>1396</td>
                <td>1374.75</td>
                <td>PLACEHOLDER</td>
                <td>1401.5</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>Mar 22</td>
                <td>1383.25</td>
                <td>-27</td>
                <td>1409.75</td>
                <td>1379</td>
                <td>PLACEHOLDER</td>
                <td>1410.25</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>May 22</td>
                <td>1391.25</td>
                <td>-27.5</td>
                <td>1418</td>
                <td>1387.5</td>
                <td>PLACEHOLDER</td>
                <td>1418.75</td>
                <td>PLACEHOLDER</td>
            </tr>
        </tbody>
        <tbody>
            <tr>
                <th colspan="9">CORN</th>
            </tr>
            <tr>
                <td>MONTH</td>
                <td>LAST</td>
                <td>CHANGE</td>
                <td>HIGH</td>
                <td>LOW</td>
                <td>SETTLE DATE</td>
                <td>SETTLE PRICE</td>
                <td>MORE</td>
            </tr>
            <tr>
                <td>Mar 22</td>
                <td>599.25</td>
                <td>-7.5</td>
                <td>608</td>
                <td>596.75</td>
                <td>PLACEHOLDER</td>
                <td>606.75</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>May 22</td>
                <td>600.75</td>
                <td>-7</td>
                <td>608.5</td>
                <td>598.25</td>
                <td>PLACEHOLDER</td>
                <td>607.75</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>Jul 22</td>
                <td>598</td>
                <td>-6.5</td>
                <td>605.25</td>
                <td>595.5</td>
                <td>PLACEHOLDER</td>
                <td>604.5</td>
                <td>PLACEHOLDER</td>
            </tr>
        </tbody>
        <tbody>
            <tr>
                <th colspan="9">WHEAT</th>
            </tr>
            <tr>
                <td>MONTH</td>
                <td>LAST</td>
                <td>CHANGE</td>
                <td>HIGH</td>
                <td>LOW</td>
                <td>SETTLE DATE</td>
                <td>SETTLE PRICE</td>
                <td>MORE</td>
            </tr>
            <tr>
                <td>Mar 22</td>
                <td>763.75</td>
                <td>5.25</td>
                <td>767.5</td>
                <td>748</td>
                <td>PLACEHOLDER</td>
                <td>758.5</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>May 22</td>
                <td>765.5</td>
                <td>5</td>
                <td>768.5</td>
                <td>750</td>
                <td>PLACEHOLDER</td>
                <td>760.5</td>
                <td>PLACEHOLDER</td>
            </tr>
            <tr>
                <td>Jul 22</td>
                <td>760.5</td>
                <td>3.5</td>
                <td>763.25</td>
                <td>747.25</td>
                <td>PLACEHOLDER</td>
                <td>757</td>
                <td>PLACEHOLDER</td>
            </tr>
        </tbody>
    </table>
</div>