diff --git a/goodtables/cells.py b/goodtables/cells.py
index 74763fb..c741a99 100644
--- a/goodtables/cells.py
+++ b/goodtables/cells.py
@@ -27,6 +27,7 @@ def create_cells(headers, schema_fields, values=None, row_number=None):
 
     iterator = zip_longest(headers, schema_fields, values or [], fillvalue=fillvalue)
     for column_number, (header, field, value) in enumerate(iterator, start=1):
+        is_virtual = header == fillvalue and value == fillvalue or None
         if header == fillvalue:
             header = None
         elif is_header_row:
@@ -35,14 +36,13 @@ def create_cells(headers, schema_fields, values=None, row_number=None):
             field = None
         if value == fillvalue:
             value = None
-
-        cell = create_cell(header, value, field, column_number, row_number)
+        cell = create_cell(header, value, field, column_number, row_number, is_virtual)
         cells.append(cell)
 
     return cells
 
 
-def create_cell(header, value=None, field=None, column_number=None, row_number=None):
+def create_cell(header, value=None, field=None, column_number=None, row_number=None, is_virtual=None):
     cell = {
         'header': header,
         'field': field,
@@ -50,6 +50,7 @@ def create_cell(header, value=None, field=None, column_number=None, row_number=N
         'column-number': column_number,
         'number': column_number,  # FIXME: Remove deprecated "number"
         'row-number': row_number,
+        'is-virtual': is_virtual,
     }
     return _remove_none_values(cell)
 
diff --git a/goodtables/checks/blank_header.py b/goodtables/checks/blank_header.py
index f9a55a0..55bcf47 100644
--- a/goodtables/checks/blank_header.py
+++ b/goodtables/checks/blank_header.py
@@ -17,7 +17,7 @@ def blank_header(cells, sample=None):
     for cell in cells:
 
         # Skip if cell have non blank header
-        if cell.get('header', False):
+        if cell.get('header', False) or cell.get('is-virtual'):
             continue
 
         # Add error
diff --git a/goodtables/checks/missing_value.py b/goodtables/checks/missing_value.py
index f7a39ad..87b4edb 100644
--- a/goodtables/checks/missing_value.py
+++ b/goodtables/checks/missing_value.py
@@ -25,7 +25,7 @@ def missing_value(cells):
         # - not having value at all - there is no `value` key
         # - having a value which is falsy (None, False, '', etc)
         # (so we don't use something like `if cell.get('value')`)
-        if 'value' in cell:
+        if 'value' in cell or cell.get('is-virtual'):
             continue
 
         # Add error

Validation report gives blank-header and missing-value, when validating 'structure' for valid csv
# Overview

When trying to validate on the structure (no schema validation involved) for a source csv, we are getting `blank-header` and `missing-value` errors, when the structure of the csv is valid.

Trying to debug de error, it seems that following piece of code is creating 'empty' columns for fields in schema not found in the source csv:
https://github.com/frictionlessdata/goodtables-py/blob/490ac37af1a9d5067ef3bff41c15940d5f63115f/goodtables/cells.py#L28-L40

Also, in relation to this issue, when also validating schema, `checks=['structure','schema']`, when executing the test case, I expect getting only a `missing-header` error, without the `header-blank` error, as there is no blank headers in the source csv.

Test to reproduce the bug:
```
# !/usr/bin/python
# -*- coding: utf-8 -*-

import json
import unittest

from goodtables import validate


DESCRIPTOR = {
    "resources": [
        {
            "name": "people",
            "data": [
                ["id", "name", "surname"],
                ["p1", "Tom", "Hanks"],
                ["p2", "Meryl", "Streep"]
            ],
            "schema": {
                "fields": [
                    {"name": "id", "type": "string"},
                    {"name": "name", "type": "string"},
                    {"name": "surname", "type": "string"},
                    {"name": "dob", "type": "date"}
                ]
            }
        }
    ]
}


class TestGoodtablesValidationReportErrors(unittest.TestCase):

    def test_structure_only_validation_should_be_valid(self):
        report = validate(DESCRIPTOR, checks=['structure'])
        errors = report["tables"][0]["errors"]

        # print("structure-only validation errors: ", json.dumps(errors, indent=4))
        self.assertFalse(errors, f"Should be valid, we are only checking structure. Found {[e['code'] for e in errors]}")

    def test_structure_and_schema_validation_should_report_only_missing_header_error(self):
        report = validate(DESCRIPTOR, checks=['structure', 'schema'])
        errors = report["tables"][0]["errors"]

        # print("full validation errors: ", json.dumps(errors, indent=4))
        self.assertTrue(
            len(errors) == 1 and errors[0].code == 'missing-header',
            f"Expected only 1 'missing-header' error, found {[e['code'] for e in errors]}")


if __name__ == '__main__':
    unittest.main()
```


---

Please preserve this line to notify @roll (lead of this repository)

diff --git a/tests/test_validate.py b/tests/test_validate.py
index cca8bc9..7e37437 100644
--- a/tests/test_validate.py
+++ b/tests/test_validate.py
@@ -368,3 +368,55 @@ def test_validate_missing_local_file_raises_source_error_issue_315(log):
     assert log(report) == [
         (1, None, None, 'io-error'),
     ]
+
+
+def test_validate_datapackage_with_schema_issue_348(log):
+    DESCRIPTOR = {
+        'resources': [
+            {
+                'name': 'people',
+                'data': [
+                    ['id', 'name', 'surname'],
+                    ['p1', 'Tom', 'Hanks'],
+                    ['p2', 'Meryl', 'Streep']
+                ],
+                'schema': {
+                    'fields': [
+                        {'name': 'id', 'type': 'string'},
+                        {'name': 'name', 'type': 'string'},
+                        {'name': 'surname', 'type': 'string'},
+                        {'name': 'dob', 'type': 'date'}
+                    ]
+                }
+            }
+        ]
+    }
+    report = validate(DESCRIPTOR, checks=['structure', 'schema'])
+    assert log(report) == [
+        (1, None, 4, 'missing-header'),
+    ]
+
+
+def test_validate_datapackage_with_schema_structure_only_issue_348(log):
+    DESCRIPTOR = {
+        'resources': [
+            {
+                'name': 'people',
+                'data': [
+                    ['id', 'name', 'surname'],
+                    ['p1', 'Tom', 'Hanks'],
+                    ['p2', 'Meryl', 'Streep']
+                ],
+                'schema': {
+                    'fields': [
+                        {'name': 'id', 'type': 'string'},
+                        {'name': 'name', 'type': 'string'},
+                        {'name': 'surname', 'type': 'string'},
+                        {'name': 'dob', 'type': 'date'}
+                    ]
+                }
+            }
+        ]
+    }
+    report = validate(DESCRIPTOR, checks=['structure'])
+    assert report['valid']

pip install --upgrade -e .[develop,ods]
parse_log_pytest
pytest
pytest
apt-get update apt-get install -y gcc
3.8
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==25.3.0
boto3==1.37.23
botocore==1.37.23
cached-property==2.0.1
cachetools==5.5.2
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
click==8.1.8
click-default-group==1.2.4
colorama==0.4.6
coverage==7.6.1
dataflows-tabulator==1.54.3
datapackage==1.15.4
distlib==0.3.9
docutils==0.20.1
et_xmlfile==2.0.0
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
ezodf==0.3.2
filelock==3.16.1
-e git+https://github.com/frictionlessdata/goodtables-py.git@9054e6b0f088e822a054c67992d9089f7312387c#egg=goodtables
greenlet==3.1.1
idna==3.10
ijson==3.3.0
importlib_resources==6.4.5
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
isodate==0.7.2
jmespath==1.0.1
jsonlines==4.0.0
jsonpointer==3.0.0
jsonschema==4.23.0
jsonschema-specifications==2023.12.1
linear-tsv==1.1.0
lxml==5.3.1
mccabe==0.7.0
mock==5.2.0
openpyxl==3.1.5
packaging==24.2
pkgutil_resolve_name==1.3.10
platformdirs==4.3.6
pluggy==1.5.0
pycodestyle==2.12.1
pydocstyle==6.3.0
pyflakes==3.2.0
pylama==8.4.1
pyproject-api==1.8.0
pytest @ file:///croot/pytest_1717793244625/work
pytest-cov==5.0.0
python-dateutil==2.9.0.post0
PyYAML==6.0.2
referencing==0.35.1
requests==2.32.3
rfc3986==2.0.0
rpds-py==0.20.1
s3transfer==0.11.4
simpleeval==0.9.13
six==1.17.0
snowballstemmer==2.2.0
SQLAlchemy==2.0.40
statistics==1.0.3.5
tableschema==1.21.0
tabulator==1.53.5
tomli==2.2.1
tox==4.25.0
typing_extensions==4.13.0
unicodecsv==0.14.1
urllib3==1.26.20
virtualenv==20.30.0
xlrd==2.0.1
zipp==3.20.2

name: goodtables-py
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py38h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=24.2=py38h06a4308_0
  - pytest=7.4.4=py38h06a4308_0
  - python=3.8.20=he870216_0
  - readline=8.2=h5eee18b_0
  - setuptools=75.1.0=py38h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.44.0=py38h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==25.3.0
      - boto3==1.37.23
      - botocore==1.37.23
      - cached-property==2.0.1
      - cachetools==5.5.2
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - click==8.1.8
      - click-default-group==1.2.4
      - colorama==0.4.6
      - coverage==7.6.1
      - dataflows-tabulator==1.54.3
      - datapackage==1.15.4
      - distlib==0.3.9
      - docutils==0.20.1
      - et-xmlfile==2.0.0
      - ezodf==0.3.2
      - filelock==3.16.1
      - greenlet==3.1.1
      - idna==3.10
      - ijson==3.3.0
      - importlib-resources==6.4.5
      - isodate==0.7.2
      - jmespath==1.0.1
      - jsonlines==4.0.0
      - jsonpointer==3.0.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2023.12.1
      - linear-tsv==1.1.0
      - lxml==5.3.1
      - mccabe==0.7.0
      - mock==5.2.0
      - openpyxl==3.1.5
      - packaging==24.2
      - pkgutil-resolve-name==1.3.10
      - platformdirs==4.3.6
      - pluggy==1.5.0
      - pycodestyle==2.12.1
      - pydocstyle==6.3.0
      - pyflakes==3.2.0
      - pylama==8.4.1
      - pyproject-api==1.8.0
      - pytest-cov==5.0.0
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.2
      - referencing==0.35.1
      - requests==2.32.3
      - rfc3986==2.0.0
      - rpds-py==0.20.1
      - s3transfer==0.11.4
      - simpleeval==0.9.13
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sqlalchemy==2.0.40
      - statistics==1.0.3.5
      - tableschema==1.21.0
      - tabulator==1.53.5
      - tomli==2.2.1
      - tox==4.25.0
      - typing-extensions==4.13.0
      - unicodecsv==0.14.1
      - urllib3==1.26.20
      - virtualenv==20.30.0
      - xlrd==2.0.1
      - zipp==3.20.2
prefix: /opt/conda/envs/goodtables-py

tests/test_validate.py::test_validate_datapackage_with_schema_issue_348 tests/test_validate.py::test_validate_datapackage_with_schema_structure_only_issue_348
tests/test_validate.py::test_validate_catch_all_open_exceptions tests/test_validate.py::test_fix_issue_312_inspector_should_report_table_as_invalid tests/test_validate.py::test_validate_missing_local_file_raises_source_error_issue_315
tests/test_validate.py::test_validate_infer_table tests/test_validate.py::test_validate_infer_datapackage_path tests/test_validate.py::test_validate_infer_datapackage_dict tests/test_validate.py::test_validate_infer_nested tests/test_validate.py::test_validate_report_scheme_format_encoding tests/test_validate.py::test_validate_report_schema tests/test_validate.py::test_validate_report_schema_infer_schema tests/test_validate.py::test_validate_nested_checks tests/test_validate.py::test_validate_datapackage_dialect_header_false tests/test_validate.py::test_source_pathlib_path_table tests/test_validate.py::test_source_pathlib_path_datapackage tests/test_validate.py::test_validate_catch_all_iter_exceptions tests/test_validate.py::test_validate_warnings_no tests/test_validate.py::test_validate_warnings_bad_datapackage_json tests/test_validate.py::test_validate_warnings_table_limit tests/test_validate.py::test_validate_warnings_row_limit tests/test_validate.py::test_validate_warnings_error_limit tests/test_validate.py::test_validate_warnings_table_and_row_limit tests/test_validate.py::test_validate_warnings_table_and_error_limit tests/test_validate.py::test_validate_empty_source tests/test_validate.py::test_validate_no_headers tests/test_validate.py::test_init_datapackage_is_correct tests/test_validate.py::test_composite_primary_key_unique_issue_215 tests/test_validate.py::test_composite_primary_key_not_unique_issue_215 tests/test_validate.py::test_validate_infer_fields_issue_223 tests/test_validate.py::test_validate_infer_fields_issue_225
goodtables/checks/blank_header.py goodtables/cells.py goodtables/checks/missing_value.py
goodtables/checks/blank_header.py goodtables/cells.py goodtables/checks/missing_value.py